update shapelib to 1.5.0. (#559)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Fri, 15 May 2020 15:04:10 +0000 (09:04 -0600)
committerGitHub <noreply@github.com>
Fri, 15 May 2020 15:04:10 +0000 (09:04 -0600)
shapelib/README.GPSBabel
shapelib/dbfopen.c
shapelib/safileio.c
shapelib/shapefil.h
shapelib/shapelib.html
shapelib/shpopen.c

index 73ead7014f3a4a127b6b6126812337cdcfcebc8d..a3f95350970444612e3f8a70ae0e3b0fc58ed77d 100644 (file)
@@ -1,4 +1,4 @@
-This is a subset of Shapelib v1.4.1 from http://shapelib.maptools.org/
+This is a subset of Shapelib v1.5.0 from http://shapelib.maptools.org/
 
 The source is unmodified.  It's subsetted here only to reduce 
 the amount of size in our tree that it takes and to reduce ongoing 
index 148e593a4eb626e933757456675bfe6e32c4219c..218db70cf0ee815cfb453c5c9f0607b23635324b 100644 (file)
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dbfopen.c,v 1.92 2016-12-05 18:44:08 erouault Exp $
+ * $Id: dbfopen.c,v 1.94 2018-08-16 15:39:07 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of .dbf access API documented in dbf_api.html.
  ******************************************************************************
  *
  * $Log: dbfopen.c,v $
+ * Revision 1.94  2018-08-16 15:39:07  erouault
+ * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
+ * internal shapelib. Mostly to allow building those files as C++
+ * without warning. Also add FTDate entry in DBFFieldType
+ * (see https://github.com/OSGeo/gdal/pull/308). And some other
+ * code cleanups
+ *
+ * Revision 1.93  2018-08-16 15:24:46  erouault
+ * * dbfopen.c: fix a bug where the end of file character was
+ * written on top of the first character of the first field name
+ * when deleting a field on a .dbf without records.
+ * Fixes https://github.com/OSGeo/gdal/issues/863
+ *
  * Revision 1.92  2016-12-05 18:44:08  erouault
  * * dbfopen.c, shapefil.h: write DBF end-of-file character 0x1A by default.
  * This behaviour can be controlled with the DBFSetWriteEndOfFileChar()
 #include "cpl_string.h"
 #else
 
+#if defined(WIN32) || defined(_WIN32)
+#    define STRCASECMP(a,b)         (stricmp(a,b))
+#  else
+#include <strings.h>
+#    define STRCASECMP(a,b)         (strcasecmp(a,b))
+#endif
+
 #if defined(_MSC_VER)
 # if _MSC_VER < 1900
 #     define snprintf _snprintf
 #define CPLsnprintf snprintf
 #endif
 
-SHP_CVSID("$Id: dbfopen.c,v 1.92 2016-12-05 18:44:08 erouault Exp $")
+SHP_CVSID("$Id: dbfopen.c,v 1.94 2018-08-16 15:39:07 erouault Exp $")
 
 #ifndef FALSE
 #  define FALSE                0
@@ -230,6 +250,18 @@ CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 #define CPL_IGNORE_RET_VAL_INT(x) x
 #endif
 
+#ifdef __cplusplus
+#define STATIC_CAST(type,x) static_cast<type>(x)
+#define REINTERPRET_CAST(type,x) reinterpret_cast<type>(x)
+#define CONST_CAST(type,x) const_cast<type>(x)
+#define SHPLIB_NULLPTR nullptr
+#else
+#define STATIC_CAST(type,x) ((type)(x))
+#define REINTERPRET_CAST(type,x) ((type)(x))
+#define CONST_CAST(type,x) ((type)(x))
+#define SHPLIB_NULLPTR NULL
+#endif
+
 /************************************************************************/
 /*                             SfRealloc()                              */
 /*                                                                      */
@@ -240,10 +272,10 @@ CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 static void * SfRealloc( void * pMem, int nNewSize )
 
 {
-    if( pMem == NULL )
-        return( (void *) malloc(nNewSize) );
+    if( pMem == SHPLIB_NULLPTR )
+        return malloc(nNewSize);
     else
-        return( (void *) realloc(pMem,nNewSize) );
+        return realloc(pMem,nNewSize);
 }
 
 /************************************************************************/
@@ -271,19 +303,19 @@ static void DBFWriteHeader(DBFHandle psDBF)
     abyHeader[0] = 0x03;               /* memo field? - just copying   */
 
     /* write out update date */
-    abyHeader[1] = (unsigned char) psDBF->nUpdateYearSince1900;
-    abyHeader[2] = (unsigned char) psDBF->nUpdateMonth;
-    abyHeader[3] = (unsigned char) psDBF->nUpdateDay;
+    abyHeader[1] = STATIC_CAST(unsigned char, psDBF->nUpdateYearSince1900);
+    abyHeader[2] = STATIC_CAST(unsigned char, psDBF->nUpdateMonth);
+    abyHeader[3] = STATIC_CAST(unsigned char, psDBF->nUpdateDay);
 
     /* record count preset at zero */
 
-    abyHeader[8] = (unsigned char) (psDBF->nHeaderLength % 256);
-    abyHeader[9] = (unsigned char) (psDBF->nHeaderLength / 256);
+    abyHeader[8] = STATIC_CAST(unsigned char, psDBF->nHeaderLength % 256);
+    abyHeader[9] = STATIC_CAST(unsigned char, psDBF->nHeaderLength / 256);
 
-    abyHeader[10] = (unsigned char) (psDBF->nRecordLength % 256);
-    abyHeader[11] = (unsigned char) (psDBF->nRecordLength / 256);
+    abyHeader[10] = STATIC_CAST(unsigned char, psDBF->nRecordLength % 256);
+    abyHeader[11] = STATIC_CAST(unsigned char, psDBF->nRecordLength / 256);
 
-    abyHeader[29] = (unsigned char) (psDBF->iLanguageDriver);
+    abyHeader[29] = STATIC_CAST(unsigned char, psDBF->iLanguageDriver);
 
 /* -------------------------------------------------------------------- */
 /*      Write the initial 32 byte file header, and all the field        */
@@ -333,7 +365,7 @@ static int DBFFlushRecord( DBFHandle psDBF )
        psDBF->bCurrentRecordModified = FALSE;
 
        nRecordOffset =
-            psDBF->nRecordLength * (SAOffset) psDBF->nCurrentRecord
+            psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nCurrentRecord)
             + psDBF->nHeaderLength;
 
        if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0
@@ -376,13 +408,13 @@ static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
             return FALSE;
 
        nRecordOffset =
-            psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+            psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
 
        if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
         {
             char szMessage[128];
             snprintf( szMessage, sizeof(szMessage), "fseek(%ld) failed on DBF file.",
-                     (long) nRecordOffset );
+                      STATIC_CAST(long, nRecordOffset) );
             psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
@@ -422,13 +454,13 @@ DBFUpdateHeader( DBFHandle psDBF )
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
     psDBF->sHooks.FRead( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
 
-    abyFileHeader[1] = (unsigned char) psDBF->nUpdateYearSince1900;
-    abyFileHeader[2] = (unsigned char) psDBF->nUpdateMonth;
-    abyFileHeader[3] = (unsigned char) psDBF->nUpdateDay;
-    abyFileHeader[4] = (unsigned char) (psDBF->nRecords % 256);
-    abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256);
-    abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256);
-    abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256);
+    abyFileHeader[1] = STATIC_CAST(unsigned char, psDBF->nUpdateYearSince1900);
+    abyFileHeader[2] = STATIC_CAST(unsigned char, psDBF->nUpdateMonth);
+    abyFileHeader[3] = STATIC_CAST(unsigned char, psDBF->nUpdateDay);
+    abyFileHeader[4] = STATIC_CAST(unsigned char, psDBF->nRecords & 0xFF);
+    abyFileHeader[5] = STATIC_CAST(unsigned char, (psDBF->nRecords>>8) & 0xFF);
+    abyFileHeader[6] = STATIC_CAST(unsigned char, (psDBF->nRecords>>16) & 0xFF);
+    abyFileHeader[7] = STATIC_CAST(unsigned char, (psDBF->nRecords>>24) & 0xFF);
 
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
     psDBF->sHooks.FWrite( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
@@ -465,6 +497,26 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
     return DBFOpenLL( pszFilename, pszAccess, &sHooks );
 }
 
+/************************************************************************/
+/*                      DBFGetLenWithoutExtension()                     */
+/************************************************************************/
+
+static int DBFGetLenWithoutExtension(const char* pszBasename)
+{
+    int i;
+    int nLen = STATIC_CAST(int, strlen(pszBasename));
+    for( i = nLen-1;
+         i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\';
+         i-- )
+    {
+        if( pszBasename[i] == '.' )
+        {
+            return i;
+        }
+    }
+    return nLen;
+}
+
 /************************************************************************/
 /*                              DBFOpen()                               */
 /*                                                                      */
@@ -478,10 +530,10 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     DBFHandle          psDBF;
     SAFile             pfCPG;
     unsigned char      *pabyBuf;
-    int                        nFields, nHeadLen, iField, i;
-    char               *pszBasename, *pszFullname;
+    int                        nFields, nHeadLen, iField;
+    char               *pszFullname;
     int                 nBufSize = 500;
-    size_t              nFullnameLen;
+    int                 nLenWithoutExtension;
 
 /* -------------------------------------------------------------------- */
 /*      We only allow the access strings "rb" and "r+".                  */
@@ -489,7 +541,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
         && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
         && strcmp(pszAccess,"r+b") != 0 )
-        return( NULL );
+        return SHPLIB_NULLPTR;
 
     if( strcmp(pszAccess,"r") == 0 )
         pszAccess = "rb";
@@ -501,46 +553,36 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 /*     Compute the base (layer) name.  If there is any extension       */
 /*     on the passed in filename we will strip it off.                 */
 /* -------------------------------------------------------------------- */
-    pszBasename = (char *) malloc(strlen(pszFilename)+5);
-    strcpy( pszBasename, pszFilename );
-    for( i = (int)strlen(pszBasename)-1;
-        i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
-              && pszBasename[i] != '\\';
-        i-- ) {}
-
-    if( pszBasename[i] == '.' )
-        pszBasename[i] = '\0';
-
-    nFullnameLen = strlen(pszBasename) + 5;
-    pszFullname = (char *) malloc(nFullnameLen);
-    snprintf( pszFullname, nFullnameLen, "%s.dbf", pszBasename );
+    nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
+    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    memcpy(pszFullname, pszFilename, nLenWithoutExtension);
+    memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
 
-    psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
+    psDBF = STATIC_CAST(DBFHandle, calloc( 1, sizeof(DBFInfo) ));
     psDBF->fp = psHooks->FOpen( pszFullname, pszAccess );
     memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
 
-    if( psDBF->fp == NULL )
+    if( psDBF->fp == SHPLIB_NULLPTR )
     {
-        snprintf( pszFullname, nFullnameLen, "%s.DBF", pszBasename );
+        memcpy(pszFullname + nLenWithoutExtension, ".DBF", 5);
         psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess );
     }
 
-    snprintf( pszFullname, nFullnameLen, "%s.cpg", pszBasename );
+    memcpy(pszFullname + nLenWithoutExtension, ".cpg", 5);
     pfCPG = psHooks->FOpen( pszFullname, "r" );
-    if( pfCPG == NULL )
+    if( pfCPG == SHPLIB_NULLPTR )
     {
-        snprintf( pszFullname, nFullnameLen, "%s.CPG", pszBasename );
+        memcpy(pszFullname + nLenWithoutExtension, ".CPG", 5);
         pfCPG = psHooks->FOpen( pszFullname, "r" );
     }
 
-    free( pszBasename );
     free( pszFullname );
 
-    if( psDBF->fp == NULL )
+    if( psDBF->fp == SHPLIB_NULLPTR )
     {
         free( psDBF );
         if( pfCPG ) psHooks->FClose( pfCPG );
-        return( NULL );
+        return SHPLIB_NULLPTR;
     }
 
     psDBF->bNoHeader = FALSE;
@@ -550,23 +592,23 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*  Read Table Header info                                              */
 /* -------------------------------------------------------------------- */
-    pabyBuf = (unsigned char *) malloc(nBufSize);
+    pabyBuf = STATIC_CAST(unsigned char *, malloc(nBufSize));
     if( psDBF->sHooks.FRead( pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp ) != 1 )
     {
         psDBF->sHooks.FClose( psDBF->fp );
         if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
         free( pabyBuf );
         free( psDBF );
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
 
     DBFSetLastModifiedDate(psDBF, pabyBuf[1], pabyBuf[2], pabyBuf[3]);
 
     psDBF->nRecords =
-     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + (pabyBuf[7] & 0x7f) *256*256*256;
+     pabyBuf[4]|(pabyBuf[5]<<8)|(pabyBuf[6]<<16)|((pabyBuf[7]&0x7f)<<24);
 
-    psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
-    psDBF->nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
+    psDBF->nHeaderLength = nHeadLen = pabyBuf[8]|(pabyBuf[9]<<8);
+    psDBF->nRecordLength = pabyBuf[10]|(pabyBuf[11]<<8);
     psDBF->iLanguageDriver = pabyBuf[29];
 
     if (psDBF->nRecordLength == 0 || nHeadLen < XBASE_FILEHDR_SZ)
@@ -575,45 +617,46 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
         if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
         free( pabyBuf );
         free( psDBF );
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
 
     psDBF->nFields = nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
 
-    psDBF->pszCurrentRecord = (char *) malloc(psDBF->nRecordLength);
+    /* coverity[tainted_data] */
+    psDBF->pszCurrentRecord = STATIC_CAST(char *, malloc(psDBF->nRecordLength));
 
 /* -------------------------------------------------------------------- */
 /*  Figure out the code page from the LDID and CPG                      */
 /* -------------------------------------------------------------------- */
 
-    psDBF->pszCodePage = NULL;
+    psDBF->pszCodePage = SHPLIB_NULLPTR;
     if( pfCPG )
     {
         size_t n;
         memset( pabyBuf, 0, nBufSize);
         psDBF->sHooks.FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
-        n = strcspn( (char *) pabyBuf, "\n\r" );
+        n = strcspn( REINTERPRET_CAST(char *, pabyBuf), "\n\r" );
         if( n > 0 )
         {
             pabyBuf[n] = '\0';
-            psDBF->pszCodePage = (char *) malloc(n + 1);
+            psDBF->pszCodePage = STATIC_CAST(char *, malloc(n + 1));
             memcpy( psDBF->pszCodePage, pabyBuf, n + 1 );
         }
                psDBF->sHooks.FClose( pfCPG );
     }
-    if( psDBF->pszCodePage == NULL && pabyBuf[29] != 0 )
+    if( psDBF->pszCodePage == SHPLIB_NULLPTR && pabyBuf[29] != 0 )
     {
-        snprintf( (char *) pabyBuf, nBufSize, "LDID/%d", psDBF->iLanguageDriver );
-        psDBF->pszCodePage = (char *) malloc(strlen((char*)pabyBuf) + 1);
-        strcpy( psDBF->pszCodePage, (char *) pabyBuf );
+        snprintf( REINTERPRET_CAST(char *, pabyBuf), nBufSize, "LDID/%d", psDBF->iLanguageDriver );
+        psDBF->pszCodePage = STATIC_CAST(char *, malloc(strlen(REINTERPRET_CAST(char*, pabyBuf)) + 1));
+        strcpy( psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf) );
     }
 
 /* -------------------------------------------------------------------- */
 /*  Read in Field Definitions                                           */
 /* -------------------------------------------------------------------- */
 
-    pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
-    psDBF->pszHeader = (char *) pabyBuf;
+    pabyBuf = STATIC_CAST(unsigned char *, SfRealloc(pabyBuf,nHeadLen));
+    psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf);
 
     psDBF->sHooks.FSeek( psDBF->fp, XBASE_FILEHDR_SZ, 0 );
     if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-XBASE_FILEHDR_SZ, 1,
@@ -622,20 +665,26 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
         psDBF->sHooks.FClose( psDBF->fp );
         free( pabyBuf );
         free( psDBF->pszCurrentRecord );
+        free( psDBF->pszCodePage );
         free( psDBF );
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
 
-    psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
-    psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
-    psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
-    psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
+    psDBF->panFieldOffset = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
+    psDBF->panFieldSize = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
+    psDBF->panFieldDecimals = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
+    psDBF->pachFieldType = STATIC_CAST(char *, malloc(sizeof(char) * nFields));
 
     for( iField = 0; iField < nFields; iField++ )
     {
        unsigned char           *pabyFInfo;
 
        pabyFInfo = pabyBuf+iField*XBASE_FLDHDR_SZ;
+        if( pabyFInfo[0] == HEADER_RECORD_TERMINATOR )
+        {
+            psDBF->nFields = iField;
+            break;
+        }
 
        if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
        {
@@ -657,7 +706,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 */
        }
 
-       psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
+       psDBF->pachFieldType[iField] = STATIC_CAST(char, pabyFInfo[11]);
        if( iField == 0 )
            psDBF->panFieldOffset[iField] = 1;
        else
@@ -665,6 +714,15 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
              psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
     }
 
+    /* Check that the total width of fields does not exceed the record width */
+    if( psDBF->nFields > 0 &&
+        psDBF->panFieldOffset[psDBF->nFields-1] +
+            psDBF->panFieldSize[psDBF->nFields-1] > psDBF->nRecordLength )
+    {
+        DBFClose( psDBF );
+        return SHPLIB_NULLPTR;
+    }
+
     DBFSetWriteEndOfFileChar( psDBF, TRUE );
 
     return( psDBF );
@@ -677,7 +735,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 void SHPAPI_CALL
 DBFClose(DBFHandle psDBF)
 {
-    if( psDBF == NULL )
+    if( psDBF == SHPLIB_NULLPTR )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -700,7 +758,7 @@ DBFClose(DBFHandle psDBF)
 /* -------------------------------------------------------------------- */
     psDBF->sHooks.FClose( psDBF->fp );
 
-    if( psDBF->panFieldOffset != NULL )
+    if( psDBF->panFieldOffset != SHPLIB_NULLPTR )
     {
         free( psDBF->panFieldOffset );
         free( psDBF->panFieldSize );
@@ -708,7 +766,7 @@ DBFClose(DBFHandle psDBF)
         free( psDBF->pachFieldType );
     }
 
-    if( psDBF->pszWorkField != NULL )
+    if( psDBF->pszWorkField != SHPLIB_NULLPTR )
         free( psDBF->pszWorkField );
 
     free( psDBF->pszHeader );
@@ -760,53 +818,42 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
 {
     DBFHandle  psDBF;
     SAFile     fp;
-    char       *pszFullname, *pszBasename;
-    int                i, ldid = -1;
+    char       *pszFullname;
+    int                ldid = -1;
     char chZero = '\0';
-    size_t      nFullnameLen;
+    int         nLenWithoutExtension;
 
 /* -------------------------------------------------------------------- */
 /*     Compute the base (layer) name.  If there is any extension       */
 /*     on the passed in filename we will strip it off.                 */
 /* -------------------------------------------------------------------- */
-    pszBasename = (char *) malloc(strlen(pszFilename)+5);
-    strcpy( pszBasename, pszFilename );
-    for( i = (int)strlen(pszBasename)-1;
-        i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
-              && pszBasename[i] != '\\';
-        i-- ) {}
-
-    if( pszBasename[i] == '.' )
-        pszBasename[i] = '\0';
-
-    nFullnameLen = strlen(pszBasename) + 5;
-    pszFullname = (char *) malloc(nFullnameLen);
-    snprintf( pszFullname, nFullnameLen, "%s.dbf", pszBasename );
+    nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
+    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    memcpy(pszFullname, pszFilename, nLenWithoutExtension);
+    memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
 
 /* -------------------------------------------------------------------- */
 /*      Create the file.                                                */
 /* -------------------------------------------------------------------- */
     fp = psHooks->FOpen( pszFullname, "wb" );
-    if( fp == NULL )
+    if( fp == SHPLIB_NULLPTR )
     {
-        free( pszBasename );
         free( pszFullname );
-        return( NULL );
+        return SHPLIB_NULLPTR;
     }
 
     psHooks->FWrite( &chZero, 1, 1, fp );
     psHooks->FClose( fp );
 
     fp = psHooks->FOpen( pszFullname, "rb+" );
-    if( fp == NULL )
+    if( fp == SHPLIB_NULLPTR )
     {
-        free( pszBasename );
         free( pszFullname );
-        return( NULL );
+        return SHPLIB_NULLPTR;
     }
 
-    snprintf( pszFullname, nFullnameLen, "%s.cpg", pszBasename );
-    if( pszCodePage != NULL )
+    memcpy(pszFullname + nLenWithoutExtension, ".cpg", 5);
+    if( pszCodePage != SHPLIB_NULLPTR )
     {
         if( strncmp( pszCodePage, "LDID/", 5 ) == 0 )
         {
@@ -817,22 +864,21 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
         if( ldid < 0 )
         {
             SAFile fpCPG = psHooks->FOpen( pszFullname, "w" );
-            psHooks->FWrite( (char*) pszCodePage, strlen(pszCodePage), 1, fpCPG );
+            psHooks->FWrite( CONST_CAST(void*, STATIC_CAST(const void*, pszCodePage)), strlen(pszCodePage), 1, fpCPG );
             psHooks->FClose( fpCPG );
         }
     }
-    if( pszCodePage == NULL || ldid >= 0 )
+    if( pszCodePage == SHPLIB_NULLPTR || ldid >= 0 )
     {
         psHooks->Remove( pszFullname );
     }
 
-    free( pszBasename );
     free( pszFullname );
 
 /* -------------------------------------------------------------------- */
 /*     Create the info structure.                                      */
 /* -------------------------------------------------------------------- */
-    psDBF = (DBFHandle) calloc(1,sizeof(DBFInfo));
+    psDBF = STATIC_CAST(DBFHandle, calloc(1,sizeof(DBFInfo)));
 
     memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
     psDBF->fp = fp;
@@ -841,23 +887,23 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
     psDBF->nRecordLength = 1;
     psDBF->nHeaderLength = XBASE_FILEHDR_SZ + 1; /* + 1 for HEADER_RECORD_TERMINATOR */
 
-    psDBF->panFieldOffset = NULL;
-    psDBF->panFieldSize = NULL;
-    psDBF->panFieldDecimals = NULL;
-    psDBF->pachFieldType = NULL;
-    psDBF->pszHeader = NULL;
+    psDBF->panFieldOffset = SHPLIB_NULLPTR;
+    psDBF->panFieldSize = SHPLIB_NULLPTR;
+    psDBF->panFieldDecimals = SHPLIB_NULLPTR;
+    psDBF->pachFieldType = SHPLIB_NULLPTR;
+    psDBF->pszHeader = SHPLIB_NULLPTR;
 
     psDBF->nCurrentRecord = -1;
     psDBF->bCurrentRecordModified = FALSE;
-    psDBF->pszCurrentRecord = NULL;
+    psDBF->pszCurrentRecord = SHPLIB_NULLPTR;
 
     psDBF->bNoHeader = TRUE;
 
     psDBF->iLanguageDriver = ldid > 0 ? ldid : 0;
-    psDBF->pszCodePage = NULL;
+    psDBF->pszCodePage = SHPLIB_NULLPTR;
     if( pszCodePage )
     {
-        psDBF->pszCodePage = (char * ) malloc( strlen(pszCodePage) + 1 );
+        psDBF->pszCodePage = STATIC_CAST(char *, malloc( strlen(pszCodePage) + 1 ));
         strcpy( psDBF->pszCodePage, pszCodePage );
     }
     DBFSetLastModifiedDate(psDBF, 95, 7, 26); /* dummy date */
@@ -882,6 +928,8 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
 
     if( eType == FTLogical )
         chNativeType = 'L';
+    else if( eType == FTDate )
+       chNativeType = 'D';
     else if( eType == FTString )
         chNativeType = 'C';
     else
@@ -974,17 +1022,17 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
 /* -------------------------------------------------------------------- */
     psDBF->nFields++;
 
-    psDBF->panFieldOffset = (int *)
-        SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+    psDBF->panFieldOffset = STATIC_CAST(int *,
+        SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ));
 
-    psDBF->panFieldSize = (int *)
-        SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+    psDBF->panFieldSize = STATIC_CAST(int *,
+        SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ));
 
-    psDBF->panFieldDecimals = (int *)
-        SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+    psDBF->panFieldDecimals = STATIC_CAST(int *,
+        SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ));
 
-    psDBF->pachFieldType = (char *)
-        SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+    psDBF->pachFieldType = STATIC_CAST(char *,
+        SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ));
 
 /* -------------------------------------------------------------------- */
 /*      Assign the new field information fields.                        */
@@ -1001,8 +1049,8 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
     psDBF->bUpdated = FALSE;
 
-    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,
-                                          psDBF->nFields*XBASE_FLDHDR_SZ);
+    psDBF->pszHeader = STATIC_CAST(char *, SfRealloc(psDBF->pszHeader,
+                                          psDBF->nFields*XBASE_FLDHDR_SZ));
 
     pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields-1);
 
@@ -1015,20 +1063,20 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
 
     if( chType == 'C' )
     {
-        pszFInfo[16] = (unsigned char) (nWidth % 256);
-        pszFInfo[17] = (unsigned char) (nWidth / 256);
+        pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
+        pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
     }
     else
     {
-        pszFInfo[16] = (unsigned char) nWidth;
-        pszFInfo[17] = (unsigned char) nDecimals;
+        pszFInfo[16] = STATIC_CAST(unsigned char, nWidth);
+        pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Make the current record buffer appropriately larger.            */
 /* -------------------------------------------------------------------- */
-    psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
-                                                 psDBF->nRecordLength);
+    psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
+                                                 psDBF->nRecordLength));
 
     /* we're done if dealing with new .dbf */
     if( psDBF->bNoHeader )
@@ -1039,13 +1087,13 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
 /* -------------------------------------------------------------------- */
 
     /* alloc record */
-    pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+    pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
 
     chFieldFill = DBFGetNullCharacter(chType);
 
     for (i = psDBF->nRecords-1; i >= 0; --i)
     {
-        nRecordOffset = nOldRecordLength * (SAOffset) i + nOldHeaderLength;
+        nRecordOffset = nOldRecordLength * STATIC_CAST(SAOffset, i) + nOldHeaderLength;
 
         /* load record */
         psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -1054,7 +1102,7 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
         /* set new field's value to NULL */
         memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
 
-        nRecordOffset = psDBF->nRecordLength * (SAOffset) i + psDBF->nHeaderLength;
+        nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, i) + psDBF->nHeaderLength;
 
         /* move record to the new place*/
         psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -1066,7 +1114,7 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
         char ch = END_OF_FILE_CHARACTER;
 
         nRecordOffset =
-            psDBF->nRecordLength * (SAOffset) psDBF->nRecords + psDBF->nHeaderLength;
+            psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
 
         psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
         psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
@@ -1097,24 +1145,24 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 
 {
     unsigned char      *pabyRec;
-    void       *pReturnField = NULL;
+    void       *pReturnField = SHPLIB_NULLPTR;
 
 /* -------------------------------------------------------------------- */
 /*      Verify selection.                                               */
 /* -------------------------------------------------------------------- */
     if( hEntity < 0 || hEntity >= psDBF->nRecords )
-        return( NULL );
+        return SHPLIB_NULLPTR;
 
     if( iField < 0 || iField >= psDBF->nFields )
-        return( NULL );
+        return SHPLIB_NULLPTR;
 
 /* -------------------------------------------------------------------- */
 /*     Have we read the record?                                        */
 /* -------------------------------------------------------------------- */
     if( !DBFLoadRecord( psDBF, hEntity ) )
-        return NULL;
+        return SHPLIB_NULLPTR;
 
-    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+    pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
 
 /* -------------------------------------------------------------------- */
 /*      Ensure we have room to extract the target field.                */
@@ -1122,18 +1170,18 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
     if( psDBF->panFieldSize[iField] >= psDBF->nWorkFieldLength )
     {
         psDBF->nWorkFieldLength = psDBF->panFieldSize[iField] + 100;
-        if( psDBF->pszWorkField == NULL )
-            psDBF->pszWorkField = (char *) malloc(psDBF->nWorkFieldLength);
+        if( psDBF->pszWorkField == SHPLIB_NULLPTR )
+            psDBF->pszWorkField = STATIC_CAST(char *, malloc(psDBF->nWorkFieldLength));
         else
-            psDBF->pszWorkField = (char *) realloc(psDBF->pszWorkField,
-                                                   psDBF->nWorkFieldLength);
+            psDBF->pszWorkField = STATIC_CAST(char *, realloc(psDBF->pszWorkField,
+                                                   psDBF->nWorkFieldLength));
     }
 
 /* -------------------------------------------------------------------- */
 /*     Extract the requested field.                                    */
 /* -------------------------------------------------------------------- */
     memcpy( psDBF->pszWorkField,
-            ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
+            REINTERPRET_CAST(const char *, pabyRec) + psDBF->panFieldOffset[iField],
             psDBF->panFieldSize[iField] );
     psDBF->pszWorkField[psDBF->panFieldSize[iField]] = '\0';
 
@@ -1176,7 +1224,7 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
     }
 #endif
 
-    return( pReturnField );
+    return pReturnField;
 }
 
 /************************************************************************/
@@ -1191,12 +1239,12 @@ DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
 {
     int        *pnValue;
 
-    pnValue = (int *) DBFReadAttribute( psDBF, iRecord, iField, 'I' );
+    pnValue = STATIC_CAST(int *, DBFReadAttribute( psDBF, iRecord, iField, 'I' ));
 
-    if( pnValue == NULL )
+    if( pnValue == SHPLIB_NULLPTR )
         return 0;
     else
-        return( *pnValue );
+        return *pnValue;
 }
 
 /************************************************************************/
@@ -1211,12 +1259,12 @@ DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
 {
     double     *pdValue;
 
-    pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+    pdValue = STATIC_CAST(double *, DBFReadAttribute( psDBF, iRecord, iField, 'N' ));
 
-    if( pdValue == NULL )
+    if( pdValue == SHPLIB_NULLPTR )
         return 0.0;
     else
-        return( *pdValue );
+        return *pdValue ;
 }
 
 /************************************************************************/
@@ -1229,7 +1277,7 @@ const char SHPAPI_CALL1(*)
 DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
 
 {
-    return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
+    return STATIC_CAST(const char *, DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
 }
 
 /************************************************************************/
@@ -1242,7 +1290,7 @@ const char SHPAPI_CALL1(*)
 DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
 
 {
-    return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
+    return STATIC_CAST(const char *, DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
 }
 
 
@@ -1256,7 +1304,7 @@ static int DBFIsValueNULL( char chType, const char* pszValue )
 {
     int i;
 
-    if( pszValue == NULL )
+    if( pszValue == SHPLIB_NULLPTR )
         return TRUE;
 
     switch(chType)
@@ -1308,7 +1356,7 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
 
     pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
 
-    if( pszValue == NULL )
+    if( pszValue == SHPLIB_NULLPTR )
         return TRUE;
 
     return DBFIsValueNULL( psDBF->pachFieldType[iField], pszValue );
@@ -1356,17 +1404,17 @@ DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
     if( iField < 0 || iField >= psDBF->nFields )
         return( FTInvalid );
 
-    if( pnWidth != NULL )
+    if( pnWidth != SHPLIB_NULLPTR )
         *pnWidth = psDBF->panFieldSize[iField];
 
-    if( pnDecimals != NULL )
+    if( pnDecimals != SHPLIB_NULLPTR )
         *pnDecimals = psDBF->panFieldDecimals[iField];
 
-    if( pszFieldName != NULL )
+    if( pszFieldName != SHPLIB_NULLPTR )
     {
        int     i;
 
-       strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*XBASE_FLDHDR_SZ,
+       strncpy( pszFieldName, STATIC_CAST(char *,psDBF->pszHeader)+iField*XBASE_FLDHDR_SZ,
                  XBASE_FLDNAME_LEN_READ );
        pszFieldName[XBASE_FLDNAME_LEN_READ] = '\0';
        for( i = XBASE_FLDNAME_LEN_READ - 1; i > 0 && pszFieldName[i] == ' '; i-- )
@@ -1374,7 +1422,10 @@ DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
     }
 
     if ( psDBF->pachFieldType[iField] == 'L' )
-       return( FTLogical);
+       return( FTLogical );
+
+    else if( psDBF->pachFieldType[iField] == 'D' )
+       return( FTDate );
 
     else if( psDBF->pachFieldType[iField] == 'N'
              || psDBF->pachFieldType[iField] == 'F' )
@@ -1436,7 +1487,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
     if( !DBFLoadRecord( psDBF, hEntity ) )
         return FALSE;
 
-    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+    pabyRec = REINTERPRET_CAST(unsigned char *,psDBF->pszCurrentRecord);
 
     psDBF->bCurrentRecordModified = TRUE;
     psDBF->bUpdated = TRUE;
@@ -1446,9 +1497,9 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 /*                                                                      */
 /*      Contributed by Jim Matthews.                                    */
 /* -------------------------------------------------------------------- */
-    if( pValue == NULL )
+    if( pValue == SHPLIB_NULLPTR )
     {
-        memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]),
+        memset( pabyRec+psDBF->panFieldOffset[iField],
                 DBFGetNullCharacter(psDBF->pachFieldType[iField]),
                 psDBF->panFieldSize[iField] );
         return TRUE;
@@ -1465,30 +1516,31 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
       {
         int            nWidth = psDBF->panFieldSize[iField];
 
-        if( (int) sizeof(szSField)-2 < nWidth )
+        if( STATIC_CAST(int,sizeof(szSField))-2 < nWidth )
             nWidth = sizeof(szSField)-2;
 
         snprintf( szFormat, sizeof(szFormat), "%%%d.%df",
                     nWidth, psDBF->panFieldDecimals[iField] );
-        CPLsnprintf(szSField, sizeof(szSField), szFormat, *((double *) pValue) );
-        if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
+        CPLsnprintf(szSField, sizeof(szSField), szFormat, *STATIC_CAST(double *, pValue) );
+        szSField[sizeof(szSField)-1] = '\0';
+        if( STATIC_CAST(int,strlen(szSField)) > psDBF->panFieldSize[iField] )
         {
             szSField[psDBF->panFieldSize[iField]] = '\0';
             nRetResult = FALSE;
         }
-        strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+        strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
             szSField, strlen(szSField) );
         break;
       }
 
       case 'L':
         if (psDBF->panFieldSize[iField] >= 1  &&
-            (*(char*)pValue == 'F' || *(char*)pValue == 'T'))
-            *(pabyRec+psDBF->panFieldOffset[iField]) = *(char*)pValue;
+            (*STATIC_CAST(char*,pValue) == 'F' || *STATIC_CAST(char*,pValue) == 'T'))
+            *(pabyRec+psDBF->panFieldOffset[iField]) = *STATIC_CAST(char*,pValue);
         break;
 
       default:
-       if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+       if( STATIC_CAST(int, strlen(STATIC_CAST(char *,pValue))) > psDBF->panFieldSize[iField] )
         {
            j = psDBF->panFieldSize[iField];
             nRetResult = FALSE;
@@ -1497,11 +1549,11 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
         {
             memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
                     psDBF->panFieldSize[iField] );
-           j = (int)strlen((char *) pValue);
+           j = STATIC_CAST(int, strlen(STATIC_CAST(char *,pValue)));
         }
 
-       strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
-               (char *) pValue, j );
+       strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
+               STATIC_CAST(const char *, pValue), j );
        break;
     }
 
@@ -1555,22 +1607,22 @@ DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
     if( !DBFLoadRecord( psDBF, hEntity ) )
         return FALSE;
 
-    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+    pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
 
 /* -------------------------------------------------------------------- */
 /*      Assign all the record fields.                                   */
 /* -------------------------------------------------------------------- */
-    if( (int)strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+    if( STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) > psDBF->panFieldSize[iField] )
         j = psDBF->panFieldSize[iField];
     else
     {
         memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
                 psDBF->panFieldSize[iField] );
-        j = (int)strlen((char *) pValue);
+        j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
     }
 
-    strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
-            (char *) pValue, j );
+    strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
+            STATIC_CAST(const char *, pValue), j );
 
     psDBF->bCurrentRecordModified = TRUE;
     psDBF->bUpdated = TRUE;
@@ -1589,7 +1641,7 @@ DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
                          double dValue )
 
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, &dValue) ) );
 }
 
 /************************************************************************/
@@ -1605,7 +1657,7 @@ DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
 {
     double     dValue = nValue;
 
-    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, &dValue) ) );
 }
 
 /************************************************************************/
@@ -1619,7 +1671,7 @@ DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
                          const char * pszValue )
 
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
+    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, CONST_CAST(char*, pszValue))) );
 }
 
 /************************************************************************/
@@ -1632,7 +1684,7 @@ int SHPAPI_CALL
 DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
 
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
+    return( DBFWriteAttribute( psDBF, iRecord, iField, SHPLIB_NULLPTR ) );
 }
 
 /************************************************************************/
@@ -1646,7 +1698,7 @@ DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
                       const char lValue)
 
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) (&lValue) ) );
+    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, CONST_CAST(char*, &lValue)) ) );
 }
 
 /************************************************************************/
@@ -1693,7 +1745,7 @@ DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
     if( !DBFLoadRecord( psDBF, hEntity ) )
         return FALSE;
 
-    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+    pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
 
     memcpy ( pabyRec, pRawTuple,  psDBF->nRecordLength );
 
@@ -1715,12 +1767,12 @@ DBFReadTuple(DBFHandle psDBF, int hEntity )
 
 {
     if( hEntity < 0 || hEntity >= psDBF->nRecords )
-        return( NULL );
+        return SHPLIB_NULLPTR;
 
     if( !DBFLoadRecord( psDBF, hEntity ) )
-        return NULL;
+        return SHPLIB_NULLPTR;
 
-    return (const char *) psDBF->pszCurrentRecord;
+    return STATIC_CAST(const char *, psDBF->pszCurrentRecord);
 }
 
 /************************************************************************/
@@ -1735,7 +1787,7 @@ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
     DBFHandle  newDBF;
 
    newDBF = DBFCreateEx ( pszFilename, psDBF->pszCodePage );
-   if ( newDBF == NULL ) return ( NULL );
+   if ( newDBF == SHPLIB_NULLPTR ) return SHPLIB_NULLPTR;
 
    newDBF->nFields = psDBF->nFields;
    newDBF->nRecordLength = psDBF->nRecordLength;
@@ -1743,17 +1795,17 @@ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
 
    if( psDBF->pszHeader )
    {
-        newDBF->pszHeader = (char *) malloc ( XBASE_FLDHDR_SZ * psDBF->nFields );
+        newDBF->pszHeader = STATIC_CAST(char *, malloc ( XBASE_FLDHDR_SZ * psDBF->nFields ));
         memcpy ( newDBF->pszHeader, psDBF->pszHeader, XBASE_FLDHDR_SZ * psDBF->nFields );
    }
 
-   newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
+   newDBF->panFieldOffset = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
    memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
-   newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
+   newDBF->panFieldSize = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
    memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
-   newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
+   newDBF->panFieldDecimals = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
    memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
-   newDBF->pachFieldType = (char *) malloc ( sizeof(char) * psDBF->nFields );
+   newDBF->pachFieldType = STATIC_CAST(char *, malloc ( sizeof(char) * psDBF->nFields ));
    memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(char)*psDBF->nFields );
 
    newDBF->bNoHeader = TRUE;
@@ -1790,22 +1842,6 @@ DBFGetNativeFieldType( DBFHandle psDBF, int iField )
     return  ' ';
 }
 
-/************************************************************************/
-/*                            str_to_upper()                            */
-/************************************************************************/
-
-static void str_to_upper (char *string)
-{
-    int len;
-    int i = -1;
-
-    len = (int)strlen (string);
-
-    while (++i < len)
-        if (isalpha(string[i]) && islower(string[i]))
-            string[i] = (char) toupper ((int)string[i]);
-}
-
 /************************************************************************/
 /*                          DBFGetFieldIndex()                          */
 /*                                                                      */
@@ -1818,23 +1854,13 @@ int SHPAPI_CALL
 DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
 
 {
-    char          name[XBASE_FLDNAME_LEN_READ+1],
-                  name1[XBASE_FLDNAME_LEN_READ+1],
-                  name2[XBASE_FLDNAME_LEN_READ+1];
+    char          name[XBASE_FLDNAME_LEN_READ+1];
     int           i;
 
-    strncpy(name1, pszFieldName,XBASE_FLDNAME_LEN_READ);
-    name1[XBASE_FLDNAME_LEN_READ] = '\0';
-    str_to_upper(name1);
-
     for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
     {
-        DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
-        strncpy(name2,name,XBASE_FLDNAME_LEN_READ);
-        name2[XBASE_FLDNAME_LEN_READ] = '\0';
-        str_to_upper(name2);
-
-        if(!strcmp(name1,name2))
+        DBFGetFieldInfo( psDBF, i, name, SHPLIB_NULLPTR, SHPLIB_NULLPTR );
+        if(!STRCASECMP(pszFieldName,name))
             return(i);
     }
     return(-1);
@@ -1916,8 +1942,8 @@ int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
 const char SHPAPI_CALL1(*)
 DBFGetCodePage(DBFHandle psDBF )
 {
-    if( psDBF == NULL )
-        return NULL;
+    if( psDBF == SHPLIB_NULLPTR )
+        return SHPLIB_NULLPTR;
     return psDBF->pszCodePage;
 }
 
@@ -1961,17 +1987,17 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     /* resize fields arrays */
     psDBF->nFields--;
 
-    psDBF->panFieldOffset = (int *)
-        SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+    psDBF->panFieldOffset = STATIC_CAST(int *,
+        SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ));
 
-    psDBF->panFieldSize = (int *)
-        SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+    psDBF->panFieldSize = STATIC_CAST(int *,
+        SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ));
 
-    psDBF->panFieldDecimals = (int *)
-        SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+    psDBF->panFieldDecimals = STATIC_CAST(int *,
+        SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ));
 
-    psDBF->pachFieldType = (char *)
-        SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+    psDBF->pachFieldType = STATIC_CAST(char *,
+        SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ));
 
     /* update header information */
     psDBF->nHeaderLength -= XBASE_FLDHDR_SZ;
@@ -1982,12 +2008,12 @@ DBFDeleteField(DBFHandle psDBF, int iField)
            psDBF->pszHeader + (iField+1)*XBASE_FLDHDR_SZ,
            sizeof(char) * (psDBF->nFields - iField)*XBASE_FLDHDR_SZ);
 
-    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,
-                                          psDBF->nFields*XBASE_FLDHDR_SZ);
+    psDBF->pszHeader = STATIC_CAST(char *, SfRealloc(psDBF->pszHeader,
+                                          psDBF->nFields*XBASE_FLDHDR_SZ));
 
     /* update size of current record appropriately */
-    psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
-                                                 psDBF->nRecordLength);
+    psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
+                                                 psDBF->nRecordLength));
 
     /* we're done if we're dealing with not yet created .dbf */
     if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
@@ -1998,20 +2024,20 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     DBFUpdateHeader( psDBF );
 
     /* alloc record */
-    pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
+    pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
 
     /* shift records to their new positions */
     for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
     {
         nRecordOffset =
-            nOldRecordLength * (SAOffset) iRecord + nOldHeaderLength;
+            nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + nOldHeaderLength;
 
         /* load record */
         psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
         psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
 
         nRecordOffset =
-            psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+            psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
 
         /* move record in two steps */
         psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -2025,6 +2051,10 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     if( psDBF->bWriteEndOfFileChar )
     {
         char ch = END_OF_FILE_CHARACTER;
+        SAOffset nEOFOffset =
+            psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+
+        psDBF->sHooks.FSeek( psDBF->fp, nEOFOffset, 0 );
         psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
     }
 
@@ -2071,12 +2101,12 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
         return FALSE;
 
     /* a simple malloc() would be enough, but calloc() helps clang static analyzer */
-    panFieldOffsetNew = (int *) calloc(sizeof(int), psDBF->nFields);
-    panFieldSizeNew = (int *) calloc(sizeof(int),  psDBF->nFields);
-    panFieldDecimalsNew = (int *) calloc(sizeof(int), psDBF->nFields);
-    pachFieldTypeNew = (char *) calloc(sizeof(char), psDBF->nFields);
-    pszHeaderNew = (char*) malloc(sizeof(char) * XBASE_FLDHDR_SZ * 
-                                  psDBF->nFields);
+    panFieldOffsetNew = STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+    panFieldSizeNew = STATIC_CAST(int *, calloc(sizeof(int),  psDBF->nFields));
+    panFieldDecimalsNew = STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+    pachFieldTypeNew = STATIC_CAST(char *, calloc(sizeof(char), psDBF->nFields));
+    pszHeaderNew = STATIC_CAST(char*, malloc(sizeof(char) * XBASE_FLDHDR_SZ * 
+                                  psDBF->nFields));
 
     /* shuffle fields definitions */
     for(i=0; i < psDBF->nFields; i++)
@@ -2104,14 +2134,14 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
         DBFUpdateHeader( psDBF );
 
         /* alloc record */
-        pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
-        pszRecordNew = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+        pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+        pszRecordNew = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
 
         /* shuffle fields in records */
         for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
         {
             nRecordOffset =
-                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+                psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
 
             /* load record */
             psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -2219,13 +2249,13 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
 
     if( chType == 'C' )
     {
-        pszFInfo[16] = (unsigned char) (nWidth % 256);
-        pszFInfo[17] = (unsigned char) (nWidth / 256);
+        pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
+        pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
     }
     else
     {
-        pszFInfo[16] = (unsigned char) nWidth;
-        pszFInfo[17] = (unsigned char) nDecimals;
+        pszFInfo[16] = STATIC_CAST(unsigned char, nWidth);
+        pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2237,8 +2267,8 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
              psDBF->panFieldOffset[i] += nWidth - nOldWidth;
         psDBF->nRecordLength += nWidth - nOldWidth;
 
-        psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
-                                                     psDBF->nRecordLength);
+        psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
+                                                     psDBF->nRecordLength));
     }
 
     /* we're done if we're dealing with not yet created .dbf */
@@ -2251,8 +2281,8 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
 
     if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
     {
-        char* pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
-        char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+        char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
+        char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
 
         /* cppcheck-suppress uninitdata */
         pszOldField[nOldWidth] = 0;
@@ -2261,7 +2291,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
         for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
         {
             nRecordOffset =
-                nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+                nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
 
             /* load record */
             psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -2272,7 +2302,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
 
             if (nWidth != nOldWidth)
             {
-                if ((chOldType == 'N' || chOldType == 'F') && pszOldField[0] == ' ')
+                if ((chOldType == 'N' || chOldType == 'F' || chOldType == 'D') && pszOldField[0] == ' ')
                 {
                     /* Strip leading spaces when truncating a numeric field */
                     memmove( pszRecord + nOffset,
@@ -2294,7 +2324,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
             }
 
             nRecordOffset =
-                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+                psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
 
             /* write record */
             psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -2306,7 +2336,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
             char ch = END_OF_FILE_CHARACTER;
 
             nRecordOffset =
-                psDBF->nRecordLength * (SAOffset) psDBF->nRecords + psDBF->nHeaderLength;
+                psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
 
             psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
             psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
@@ -2318,8 +2348,8 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
     }
     else if (nWidth > nOldWidth)
     {
-        char* pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
-        char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+        char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+        char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
 
         /* cppcheck-suppress uninitdata */
         pszOldField[nOldWidth] = 0;
@@ -2328,7 +2358,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
         for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
         {
             nRecordOffset =
-                nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+                nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
 
             /* load record */
             psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -2366,7 +2396,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
             }
 
             nRecordOffset =
-                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+                psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
 
             /* write record */
             psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
@@ -2378,7 +2408,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
             char ch = END_OF_FILE_CHARACTER;
 
             nRecordOffset =
-                psDBF->nRecordLength * (SAOffset) psDBF->nRecords + psDBF->nHeaderLength;
+                psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
 
             psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
             psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
index 533e7ada35b90f957bacf6c29c7ea62fcefcb664..d2c7f581c5a954eff5dd68fff5635851fb88bf5e 100644 (file)
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: safileio.c,v 1.5 2016-12-05 12:44:05 erouault Exp $
+ * $Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Default implementation of file io based on stdio.
  ******************************************************************************
  *
  * $Log: safileio.c,v $
+ * Revision 1.6  2018-06-15 19:56:32  erouault
+ * * safileio.c: remove duplicate test. Patch by Jaroslav Fojtik.
+ * Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2744
+ *
  * Revision 1.5  2016-12-05 12:44:05  erouault
  * * Major overhaul of Makefile build system to use autoconf/automake.
  *
@@ -70,7 +74,7 @@
 #include <string.h>
 #include <stdio.h>
 
-SHP_CVSID("$Id: safileio.c,v 1.5 2016-12-05 12:44:05 erouault Exp $");
+SHP_CVSID("$Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $");
 
 #ifdef SHPAPI_UTF8_HOOKS
 #   ifdef SHPAPI_WINDOWS
@@ -236,7 +240,7 @@ SAFile SAUtf8WFOpen( const char *pszFilename, const char *pszAccess )
     const wchar_t *pwszFileName, *pwszAccess;
     pwszFileName = Utf8ToWideChar( pszFilename );
     pwszAccess = Utf8ToWideChar( pszAccess );
-    if( pwszFileName != NULL && pwszFileName != NULL)
+    if( pwszFileName != NULL && pwszAccess != NULL)
     {
         file = (SAFile) _wfopen( pwszFileName, pwszAccess );
     }
index 08c64599622193e0766925d1ee3db93eb0afa3e9..199964d428ede7bf041ec1beb243a1f77fef152f 100644 (file)
@@ -2,7 +2,7 @@
 #define SHAPEFILE_H_INCLUDED
 
 /******************************************************************************
- * $Id: shapefil.h,v 1.55 2016-12-05 18:44:08 erouault Exp $
+ * $Id: shapefil.h,v 1.56 2018-08-16 15:39:07 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Primary include file for Shapelib.
  ******************************************************************************
  *
  * $Log: shapefil.h,v $
+ * Revision 1.56  2018-08-16 15:39:07  erouault
+ * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
+ * internal shapelib. Mostly to allow building those files as C++
+ * without warning. Also add FTDate entry in DBFFieldType
+ * (see https://github.com/OSGeo/gdal/pull/308). And some other
+ * code cleanups
+ *
  * Revision 1.55  2016-12-05 18:44:08  erouault
  * * dbfopen.c, shapefil.h: write DBF end-of-file character 0x1A by default.
  * This behaviour can be controlled with the DBFSetWriteEndOfFileChar()
@@ -631,6 +638,7 @@ typedef enum {
   FTInteger,
   FTDouble,
   FTLogical,
+  FTDate,
   FTInvalid
 } DBFFieldType;
 
index 19a433604c48c54bdd4cfe59e0e67d7a8c2a9286..fa81f91aa6aefdf76b0b945aaf3b54146c10a368 100644 (file)
@@ -68,9 +68,8 @@ Shapelib is hosted at
 <a href="http://shapelib.maptools.org">shapelib.maptools.org</a>.   A mailing
 list for discussion of how to use shapelib, and announcing new releases 
 <a href="http://lists.maptools.org/mailman/listinfo/shapelib/">is 
-available</a>.  To only find out about new releases of Shapelib select the 
-"<i>Subscribe to new releases</i>" option from the link at 
-<a href="http://freshmeat.net/projects/shapelib/">Freshmeat</a>.<p>
+available</a>. To get notification of new releases of Shapelib <i>subscribe</i> to 
+the project mailing list at https://lists.osgeo.org/pipermail/shapelib/.<p>
 
 <h2>Credits</h2>
 
index f9d28c23d3dcf4613230b818b309d3d33d9e21ee..2fcff96dabae68aeb7b33b65cadf105328645176 100644 (file)
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shpopen.c,v 1.76 2017-09-10 10:11:36 erouault Exp $
+ * $Id: shpopen.c,v 1.78 2019-02-28 15:55:23 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of core Shapefile read/write functions.
  ******************************************************************************
  *
  * $Log: shpopen.c,v $
+ * Revision 1.78  2019-02-28 15:55:23  erouault
+ * * shpopen.c: resync with GDAL internal shapelib to avoid being dependent
+ * on correctness of file size field in .shp. Fixes
+ * https://lists.osgeo.org/pipermail/gdal-dev/2018-October/049218.html
+ *
+ * Revision 1.77  2018-08-16 15:39:07  erouault
+ * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
+ * internal shapelib. Mostly to allow building those files as C++
+ * without warning. Also add FTDate entry in DBFFieldType
+ * (see https://github.com/OSGeo/gdal/pull/308). And some other
+ * code cleanups
+ *
  * Revision 1.76  2017-09-10 10:11:36  erouault
  * * shpopen.c: resync with GDAL copy. Make sure to zero terminate all
  * error messages. And fix regression regarding re-writing the last shape
 #include <stdio.h>
 #include <errno.h>
 
-SHP_CVSID("$Id: shpopen.c,v 1.76 2017-09-10 10:11:36 erouault Exp $")
+SHP_CVSID("$Id: shpopen.c,v 1.78 2019-02-28 15:55:23 erouault Exp $")
 
 typedef unsigned char uchar;
 
@@ -351,6 +363,14 @@ typedef unsigned int             int32;
 static int     bBigEndian;
 #endif
 
+#ifdef __cplusplus
+#define STATIC_CAST(type,x) static_cast<type>(x)
+#define SHPLIB_NULLPTR nullptr
+#else
+#define STATIC_CAST(type,x) ((type)(x))
+#define SHPLIB_NULLPTR NULL
+#endif
+
 /************************************************************************/
 /*                              SwapWord()                              */
 /*                                                                      */
@@ -365,9 +385,9 @@ static void SwapWord( int length, void * wordP )
 
     for( i=0; i < length/2; i++ )
     {
-       temp = ((uchar *) wordP)[i];
-       ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
-       ((uchar *) wordP)[length-i-1] = temp;
+       temp = STATIC_CAST(uchar*, wordP)[i];
+       STATIC_CAST(uchar*, wordP)[i] = STATIC_CAST(uchar*, wordP)[length-i-1];
+       STATIC_CAST(uchar*, wordP)[length-i-1] = temp;
     }
 }
 
@@ -381,10 +401,10 @@ static void       SwapWord( int length, void * wordP )
 static void * SfRealloc( void * pMem, int nNewSize )
 
 {
-    if( pMem == NULL )
-        return( (void *) malloc(nNewSize) );
+    if( pMem == SHPLIB_NULLPTR )
+        return malloc(nNewSize);
     else
-        return( (void *) realloc(pMem,nNewSize) );
+        return realloc(pMem,nNewSize);
 }
 
 /************************************************************************/
@@ -403,7 +423,7 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
     double     dValue;
     int32      *panSHX;
 
-    if (psSHP->fpSHX == NULL)
+    if (psSHP->fpSHX == SHPLIB_NULLPTR)
     {
         psSHP->sHooks.Error( "SHPWriteHeader failed : SHX file is closed");
         return;
@@ -498,8 +518,8 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
 /* -------------------------------------------------------------------- */
 /*      Write out the .shx contents.                                    */
 /* -------------------------------------------------------------------- */
-    panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
-    if( panSHX == NULL )
+    panSHX = STATIC_CAST(int32 *, malloc(sizeof(int32) * 2 * psSHP->nRecords));
+    if( panSHX == SHPLIB_NULLPTR )
     {
         psSHP->sHooks.Error( "Failure allocatin panSHX" );
         return;
@@ -513,7 +533,7 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
         if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
     }
 
-    if( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX )
+    if( STATIC_CAST(int, psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX ))
         != psSHP->nRecords )
     {
         char szErrorMsg[200];
@@ -548,6 +568,26 @@ SHPOpen( const char * pszLayer, const char * pszAccess )
     return SHPOpenLL( pszLayer, pszAccess, &sHooks );
 }
 
+/************************************************************************/
+/*                      SHPGetLenWithoutExtension()                     */
+/************************************************************************/
+
+static int SHPGetLenWithoutExtension(const char* pszBasename)
+{
+    int i;
+    int nLen = STATIC_CAST(int, strlen(pszBasename));
+    for( i = nLen-1;
+         i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\';
+         i-- )
+    {
+        if( pszBasename[i] == '.' )
+        {
+            return i;
+        }
+    }
+    return nLen;
+}
+
 /************************************************************************/
 /*                              SHPOpen()                               */
 /*                                                                      */
@@ -559,14 +599,14 @@ SHPHandle SHPAPI_CALL
 SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 
 {
-    char        *pszFullname, *pszBasename;
+    char        *pszFullname;
     SHPHandle       psSHP;
 
     uchar       *pabyBuf;
     int         i;
     double      dValue;
     int         bLazySHXLoading = FALSE;
-    size_t nFullnameLen;
+    int         nLenWithoutExtension;
 
 /* -------------------------------------------------------------------- */
 /*      Ensure the access string is one of the legal ones.  We          */
@@ -578,7 +618,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         pszAccess = "r+b";
     else
     {
-        bLazySHXLoading = strchr(pszAccess, 'l') != NULL;
+        bLazySHXLoading = strchr(pszAccess, 'l') != SHPLIB_NULLPTR;
         pszAccess = "rb";
     }
 
@@ -596,90 +636,85 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*  Initialize the info structure.                  */
 /* -------------------------------------------------------------------- */
-    psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
+    psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo),1));
 
     psSHP->bUpdated = FALSE;
     memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
 
-/* -------------------------------------------------------------------- */
-/*  Compute the base (layer) name.  If there is any extension   */
-/*  on the passed in filename we will strip it off.         */
-/* -------------------------------------------------------------------- */
-    pszBasename = (char *) malloc(strlen(pszLayer)+5);
-    strcpy( pszBasename, pszLayer );
-    for( i = (int)strlen(pszBasename)-1;
-         i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
-             && pszBasename[i] != '\\';
-         i-- ) {}
-
-    if( pszBasename[i] == '.' )
-        pszBasename[i] = '\0';
-
 /* -------------------------------------------------------------------- */
 /*  Open the .shp and .shx files.  Note that files pulled from  */
 /*  a PC to Unix with upper case filenames won't work!      */
 /* -------------------------------------------------------------------- */
-    nFullnameLen = strlen(pszBasename) + 5;
-    pszFullname = (char *) malloc(nFullnameLen);
-    snprintf( pszFullname, nFullnameLen, "%s.shp", pszBasename ) ;
+    nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    memcpy(pszFullname, pszLayer, nLenWithoutExtension);
+    memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
     psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
-    if( psSHP->fpSHP == NULL )
+    if( psSHP->fpSHP == SHPLIB_NULLPTR )
     {
-        snprintf( pszFullname, nFullnameLen, "%s.SHP", pszBasename );
+        memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
         psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
     }
 
-    if( psSHP->fpSHP == NULL )
+    if( psSHP->fpSHP == SHPLIB_NULLPTR )
     {
-        size_t nMessageLen = strlen(pszBasename)*2+256;
-        char *pszMessage = (char *) malloc(nMessageLen);
+        size_t nMessageLen = strlen(pszFullname)*2+256;
+        char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+        pszFullname[nLenWithoutExtension] = 0;
         snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
-                  pszBasename, pszBasename );
+                  pszFullname, pszFullname );
         psHooks->Error( pszMessage );
         free( pszMessage );
 
         free( psSHP );
-        free( pszBasename );
         free( pszFullname );
 
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
 
-    snprintf( pszFullname, nFullnameLen, "%s.shx", pszBasename );
+    memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
     psSHP->fpSHX =  psSHP->sHooks.FOpen(pszFullname, pszAccess );
-    if( psSHP->fpSHX == NULL )
+    if( psSHP->fpSHX == SHPLIB_NULLPTR )
     {
-        snprintf( pszFullname, nFullnameLen, "%s.SHX", pszBasename );
+        memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
         psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
     }
 
-    if( psSHP->fpSHX == NULL )
+    if( psSHP->fpSHX == SHPLIB_NULLPTR )
     {
-        size_t nMessageLen = strlen(pszBasename)*2+256;
-        char *pszMessage = (char *) malloc(nMessageLen);
-        snprintf( pszMessage, nMessageLen, "Unable to open %s.shx or %s.SHX."
-                  "Try --config SHAPE_RESTORE_SHX true to restore or create it",
-                  pszBasename, pszBasename );
+        size_t nMessageLen = strlen(pszFullname)*2+256;
+        char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
+        pszFullname[nLenWithoutExtension] = 0;
+        snprintf( pszMessage, nMessageLen, "Unable to open %s.shx or %s.SHX. "
+                  "Set SHAPE_RESTORE_SHX config option to YES to restore or "
+                  "create it.", pszFullname, pszFullname );
         psHooks->Error( pszMessage );
         free( pszMessage );
 
         psSHP->sHooks.FClose( psSHP->fpSHP );
         free( psSHP );
-        free( pszBasename );
         free( pszFullname );
-        return( NULL );
+        return SHPLIB_NULLPTR ;
     }
 
     free( pszFullname );
-    free( pszBasename );
 
 /* -------------------------------------------------------------------- */
 /*  Read the file size from the SHP file.               */
 /* -------------------------------------------------------------------- */
-    pabyBuf = (uchar *) malloc(100);
-    psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
+    pabyBuf = STATIC_CAST(uchar *, malloc(100));
+    if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP ) != 1 )
+    {
+        psSHP->sHooks.Error( ".shp file is unreadable, or corrupt." );
+        psSHP->sHooks.FClose( psSHP->fpSHP );
+        psSHP->sHooks.FClose( psSHP->fpSHX );
+        free( pabyBuf );
+        free( psSHP );
+
+        return SHPLIB_NULLPTR ;
+    }
 
-    psSHP->nFileSize = ((unsigned int)pabyBuf[24]<<24)|(pabyBuf[25]<<16)|
+    psSHP->nFileSize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
                         (pabyBuf[26]<<8)|pabyBuf[27];
     if( psSHP->nFileSize < UINT_MAX / 2 )
         psSHP->nFileSize *= 2;
@@ -701,7 +736,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         free( pabyBuf );
         free( psSHP );
 
-        return( NULL );
+        return SHPLIB_NULLPTR;
     }
 
     psSHP->nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
@@ -725,7 +760,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         free( psSHP );
         free(pabyBuf);
 
-        return( NULL );
+        return SHPLIB_NULLPTR;
     }
 
     /* If a lot of records are advertized, check that the file is big enough */
@@ -736,9 +771,9 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 2 );
         nFileSize = psSHP->sHooks.FTell( psSHP->fpSHX );
         if( nFileSize > 100 &&
-            nFileSize/2 < (SAOffset)(psSHP->nRecords * 4 + 50) )
+            nFileSize/2 < STATIC_CAST(SAOffset, psSHP->nRecords * 4 + 50) )
         {
-            psSHP->nRecords = (int)((nFileSize - 100) / 8);
+            psSHP->nRecords = STATIC_CAST(int, (nFileSize - 100) / 8);
         }
         psSHP->sHooks.FSeek( psSHP->fpSHX, 100, 0 );
     }
@@ -786,18 +821,18 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
     psSHP->nMaxRecords = psSHP->nRecords;
 
-    psSHP->panRecOffset = (unsigned int *)
-        malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
-    psSHP->panRecSize = (unsigned int *)
-        malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
+    psSHP->panRecOffset = STATIC_CAST(unsigned int *,
+        malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
+    psSHP->panRecSize = STATIC_CAST(unsigned int *,
+        malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
     if( bLazySHXLoading )
-        pabyBuf = NULL;
+        pabyBuf = SHPLIB_NULLPTR;
     else
-        pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
+        pabyBuf = STATIC_CAST(uchar *, malloc(8 * MAX(1,psSHP->nRecords) ));
 
-    if (psSHP->panRecOffset == NULL ||
-        psSHP->panRecSize == NULL ||
-        (!bLazySHXLoading && pabyBuf == NULL))
+    if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
+        psSHP->panRecSize == SHPLIB_NULLPTR ||
+        (!bLazySHXLoading && pabyBuf == SHPLIB_NULLPTR))
     {
         char szErrorMsg[200];
 
@@ -813,17 +848,18 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         if (psSHP->panRecSize) free( psSHP->panRecSize );
         if (pabyBuf) free( pabyBuf );
         free( psSHP );
-        return( NULL );
+        return SHPLIB_NULLPTR;
     }
 
     if( bLazySHXLoading )
     {
         memset(psSHP->panRecOffset, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
         memset(psSHP->panRecSize, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
+        free( pabyBuf ); // sometimes make cppcheck happy, but
         return( psSHP );
     }
 
-    if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )
+    if( STATIC_CAST(int, psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ))
         != psSHP->nRecords )
     {
         char szErrorMsg[200];
@@ -842,14 +878,14 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         free( pabyBuf );
         free( psSHP );
 
-        return( NULL );
+        return SHPLIB_NULLPTR;
     }
 
     /* In read-only mode, we can close the SHX now */
     if (strcmp(pszAccess, "rb") == 0)
     {
         psSHP->sHooks.FClose( psSHP->fpSHX );
-        psSHP->fpSHX = NULL;
+        psSHP->fpSHX = SHPLIB_NULLPTR;
     }
 
     for( i = 0; i < psSHP->nRecords; i++ )
@@ -862,7 +898,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
         if( !bBigEndian ) SwapWord( 4, &nLength );
 
-        if( nOffset > (unsigned int)INT_MAX )
+        if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
         {
             char str[128];
             snprintf( str, sizeof(str),
@@ -872,9 +908,9 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
             psSHP->sHooks.Error( str );
             SHPClose(psSHP);
             free( pabyBuf );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
-        if( nLength > (unsigned int)(INT_MAX / 2 - 4) )
+        if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
         {
             char str[128];
             snprintf( str, sizeof(str),
@@ -884,7 +920,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
             psSHP->sHooks.Error( str );
             SHPClose(psSHP);
             free( pabyBuf );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
         psSHP->panRecOffset[i] = nOffset*2;
         psSHP->panRecSize[i] = nLength*2;
@@ -916,7 +952,7 @@ SHPOpenLLEx( const char * pszLayer, const char * pszAccess, SAHooks *psHooks,
         }
     }
 
-    return( NULL );
+    return SHPLIB_NULLPTR;
 }
 
 /************************************************************************/
@@ -930,18 +966,14 @@ int       SHPAPI_CALL
 SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 
 {
-    char            *pszFullname, *pszBasename;
+    char            *pszFullname;
     SAFile          fpSHP, fpSHX;
 
 
     uchar           *pabyBuf;
-    int             i;
-    size_t          nFullnameLen;
+    int             nLenWithoutExtension;
     unsigned int    nSHPFilesize;
 
-    size_t          nMessageLen;
-    char            *pszMessage;
-
     unsigned int    nCurrentRecordOffset = 0;
     unsigned int    nCurrentSHPOffset = 100;
     size_t          nRealSHXContentSize = 100;
@@ -970,51 +1002,41 @@ SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks
 /*  Establish the byte order on this machine.                           */
 /* -------------------------------------------------------------------- */
 #if !defined(bBigEndian)
-    i = 1;
-    if( *((uchar *) &i) == 1 )
-        bBigEndian = FALSE;
-    else
-        bBigEndian = TRUE;
+    {
+        int i = 1;
+        if( *((uchar *) &i) == 1 )
+            bBigEndian = FALSE;
+        else
+            bBigEndian = TRUE;
+    }
 #endif
 
-/* -------------------------------------------------------------------- */
-/*  Compute the base (layer) name.  If there is any extension           */
-/*  on the passed in filename we will strip it off.                     */
-/* -------------------------------------------------------------------- */
-    pszBasename = (char *) malloc(strlen(pszLayer)+5);
-    strcpy( pszBasename, pszLayer );
-    for( i = (int)strlen(pszBasename)-1;
-         i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
-             && pszBasename[i] != '\\';
-         i-- ) {}
-
-    if( pszBasename[i] == '.' )
-        pszBasename[i] = '\0';
-
 /* -------------------------------------------------------------------- */
 /*  Open the .shp file.  Note that files pulled from                    */
 /*  a PC to Unix with upper case filenames won't work!                  */
 /* -------------------------------------------------------------------- */
-    nFullnameLen = strlen(pszBasename) + 5;
-    pszFullname = (char *) malloc(nFullnameLen);
-    snprintf( pszFullname, nFullnameLen, "%s.shp", pszBasename ) ;
+    nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    memcpy(pszFullname, pszLayer, nLenWithoutExtension);
+    memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
     fpSHP = psHooks->FOpen(pszFullname, pszAccess );
-    if( fpSHP == NULL )
+    if( fpSHP == SHPLIB_NULLPTR )
     {
-        snprintf( pszFullname, nFullnameLen, "%s.SHP", pszBasename );
+        memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
         fpSHP = psHooks->FOpen(pszFullname, pszAccess );
     }
 
-    if( fpSHP == NULL )
+    if( fpSHP == SHPLIB_NULLPTR )
     {
-        nMessageLen = strlen(pszBasename)*2+256;
-        pszMessage = (char *) malloc(nMessageLen);
+        size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
+        char* pszMessage = STATIC_CAST(char *, malloc( nMessageLen ));
+
+        pszFullname[nLenWithoutExtension] = 0;
         snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
-                  pszBasename, pszBasename );
+                  pszFullname, pszFullname );
         psHooks->Error( pszMessage );
         free( pszMessage );
 
-        free( pszBasename );
         free( pszFullname );
 
         return( 0 );
@@ -1023,32 +1045,38 @@ SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks
 /* -------------------------------------------------------------------- */
 /*  Read the file size from the SHP file.                               */
 /* -------------------------------------------------------------------- */
-    pabyBuf = (uchar *) malloc(100);
+    pabyBuf = STATIC_CAST(uchar *, malloc(100));
     psHooks->FRead( pabyBuf, 100, 1, fpSHP );
 
-    nSHPFilesize = ((unsigned int)pabyBuf[24]<<24)|(pabyBuf[25]<<16)|
+    nSHPFilesize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
                    (pabyBuf[26]<<8)|pabyBuf[27];
     if( nSHPFilesize < UINT_MAX / 2 )
         nSHPFilesize *= 2;
     else
         nSHPFilesize = (UINT_MAX / 2) * 2;
 
-    snprintf( pszFullname, nFullnameLen, "%s.shx", pszBasename );
+    memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
     fpSHX = psHooks->FOpen( pszFullname, pszSHXAccess );
+    if( fpSHX == SHPLIB_NULLPTR )
+    {
+        memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
+        fpSHP = psHooks->FOpen(pszFullname, pszAccess );
+    }
 
-    if( fpSHX == NULL )
+    if( fpSHX == SHPLIB_NULLPTR )
     {
-        nMessageLen = strlen( pszBasename ) * 2 + 256;
-        pszMessage = (char *) malloc( nMessageLen );
-        snprintf( pszMessage, nMessageLen, "Error opening file %s.shx for writing",
-                 pszBasename );
+        size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
+        char* pszMessage = STATIC_CAST(char *, malloc( nMessageLen ));
+        pszFullname[nLenWithoutExtension] = 0;
+        snprintf( pszMessage, nMessageLen,
+                  "Error opening file %s.shx or %s.SHX for writing",
+                  pszFullname, pszFullname );
         psHooks->Error( pszMessage );
         free( pszMessage );
 
         psHooks->FClose( fpSHX );
 
         free( pabyBuf );
-        free( pszBasename );
         free( pszFullname );
 
         return( 0 );
@@ -1058,7 +1086,7 @@ SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks
 /*  Open SHX and create it using SHP file content.                      */
 /* -------------------------------------------------------------------- */
     psHooks->FSeek( fpSHP, 100, 0 );
-    pabySHXHeader = (char *) malloc ( 100 );
+    pabySHXHeader = STATIC_CAST(char *, malloc ( 100 ));
     memcpy( pabySHXHeader, pabyBuf, 100 );
     psHooks->FWrite( pabySHXHeader, 100, 1, fpSHX );
 
@@ -1090,7 +1118,6 @@ SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks
             psHooks->FClose( fpSHP );
 
             free( pabySHXHeader );
-            free( pszBasename );
             free( pszFullname );
 
             return( 0 );
@@ -1107,7 +1134,6 @@ SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks
 
     free ( pabyBuf );
     free ( pszFullname );
-    free ( pszBasename );
     free ( pabySHXHeader );
 
     return( 1 );
@@ -1123,7 +1149,7 @@ void SHPAPI_CALL
 SHPClose(SHPHandle psSHP )
 
 {
-    if( psSHP == NULL )
+    if( psSHP == SHPLIB_NULLPTR )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -1138,20 +1164,20 @@ SHPClose(SHPHandle psSHP )
     free( psSHP->panRecOffset );
     free( psSHP->panRecSize );
 
-    if ( psSHP->fpSHX != NULL)
+    if ( psSHP->fpSHX != SHPLIB_NULLPTR)
         psSHP->sHooks.FClose( psSHP->fpSHX );
     psSHP->sHooks.FClose( psSHP->fpSHP );
 
-    if( psSHP->pabyRec != NULL )
+    if( psSHP->pabyRec != SHPLIB_NULLPTR )
     {
         free( psSHP->pabyRec );
     }
 
-    if( psSHP->pabyObjectBuf != NULL )
+    if( psSHP->pabyObjectBuf != SHPLIB_NULLPTR )
     {
         free( psSHP->pabyObjectBuf );
     }
-    if( psSHP->psCachedObject != NULL )
+    if( psSHP->psCachedObject != SHPLIB_NULLPTR )
     {
         free( psSHP->psCachedObject );
     }
@@ -1171,10 +1197,10 @@ void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode )
 {
     if( bFastMode )
     {
-        if( hSHP->psCachedObject == NULL )
+        if( hSHP->psCachedObject == SHPLIB_NULLPTR )
         {
-            hSHP->psCachedObject = (SHPObject*) calloc(1, sizeof(SHPObject));
-            assert( hSHP->psCachedObject != NULL );
+            hSHP->psCachedObject = STATIC_CAST(SHPObject*, calloc(1, sizeof(SHPObject)));
+            assert( hSHP->psCachedObject != SHPLIB_NULLPTR );
         }
     }
 
@@ -1194,20 +1220,20 @@ SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
 {
     int                i;
 
-    if( psSHP == NULL )
+    if( psSHP == SHPLIB_NULLPTR )
         return;
 
-    if( pnEntities != NULL )
+    if( pnEntities != SHPLIB_NULLPTR )
         *pnEntities = psSHP->nRecords;
 
-    if( pnShapeType != NULL )
+    if( pnShapeType != SHPLIB_NULLPTR )
         *pnShapeType = psSHP->nShapeType;
 
     for( i = 0; i < 4; i++ )
     {
-        if( padfMinBound != NULL )
+        if( padfMinBound != SHPLIB_NULLPTR )
             padfMinBound[i] = psSHP->adBoundsMin[i];
-        if( padfMaxBound != NULL )
+        if( padfMaxBound != SHPLIB_NULLPTR )
             padfMaxBound[i] = psSHP->adBoundsMax[i];
     }
 }
@@ -1241,47 +1267,36 @@ SHPHandle SHPAPI_CALL
 SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 
 {
-    char       *pszBasename = NULL, *pszFullname = NULL;
-    int                i;
-    SAFile     fpSHP = NULL, fpSHX = NULL;
+    char       *pszFullname;
+    SAFile     fpSHP;
+    SAFile      fpSHX = SHPLIB_NULLPTR;
     uchar      abyHeader[100];
     int32      i32;
     double     dValue;
-    size_t      nFullnameLen;
+    int         nLenWithoutExtension;
 
 /* -------------------------------------------------------------------- */
 /*      Establish the byte order on this system.                        */
 /* -------------------------------------------------------------------- */
 #if !defined(bBigEndian)
-    i = 1;
-    if( *((uchar *) &i) == 1 )
-        bBigEndian = FALSE;
-    else
-        bBigEndian = TRUE;
+    {
+        int i = 1;
+        if( *((uchar *) &i) == 1 )
+            bBigEndian = FALSE;
+        else
+            bBigEndian = TRUE;
+    }
 #endif
 
-/* -------------------------------------------------------------------- */
-/*     Compute the base (layer) name.  If there is any extension       */
-/*     on the passed in filename we will strip it off.                 */
-/* -------------------------------------------------------------------- */
-    pszBasename = (char *) malloc(strlen(pszLayer)+5);
-    strcpy( pszBasename, pszLayer );
-    for( i = (int)strlen(pszBasename)-1;
-         i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
-             && pszBasename[i] != '\\';
-         i-- ) {}
-
-    if( pszBasename[i] == '.' )
-        pszBasename[i] = '\0';
-
 /* -------------------------------------------------------------------- */
 /*      Open the two files so we can write their headers.               */
 /* -------------------------------------------------------------------- */
-    nFullnameLen = strlen(pszBasename) + 5;
-    pszFullname = (char *) malloc(nFullnameLen);
-    snprintf( pszFullname, nFullnameLen, "%s.shp", pszBasename );
+    nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    memcpy(pszFullname, pszLayer, nLenWithoutExtension);
+    memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
     fpSHP = psHooks->FOpen(pszFullname, "wb" );
-    if( fpSHP == NULL )
+    if( fpSHP == SHPLIB_NULLPTR )
     {
         char szErrorMsg[200];
         snprintf( szErrorMsg, sizeof(szErrorMsg),
@@ -1292,9 +1307,9 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
         goto error;
     }
 
-    snprintf( pszFullname, nFullnameLen, "%s.shx", pszBasename );
+    memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
     fpSHX = psHooks->FOpen(pszFullname, "wb" );
-    if( fpSHX == NULL )
+    if( fpSHX == SHPLIB_NULLPTR )
     {
         char szErrorMsg[200];
         snprintf( szErrorMsg, sizeof(szErrorMsg),
@@ -1304,8 +1319,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
         goto error;
     }
 
-    free( pszFullname ); pszFullname = NULL;
-    free( pszBasename ); pszBasename = NULL;
+    free( pszFullname ); pszFullname = SHPLIB_NULLPTR;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare header block for .shp file.                             */
@@ -1377,10 +1391,9 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 
 error:
     if (pszFullname) free(pszFullname);
-    if (pszBasename) free(pszBasename);
     if (fpSHP) psHooks->FClose( fpSHP );
     if (fpSHX) psHooks->FClose( fpSHX );
-    return NULL;
+    return SHPLIB_NULLPTR;
 }
 
 /************************************************************************/
@@ -1462,7 +1475,7 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
     SHPObject  *psObject;
     int                i, bHasM, bHasZ;
 
-    psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
+    psObject = STATIC_CAST(SHPObject *, calloc(1,sizeof(SHPObject)));
     psObject->nSHPType = nSHPType;
     psObject->nShapeId = nShapeId;
     psObject->bMeasureIsUsed = FALSE;
@@ -1504,20 +1517,20 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
     {
         psObject->nParts = MAX(1,nParts);
 
-        psObject->panPartStart = (int *)
-            calloc(sizeof(int), psObject->nParts);
-        psObject->panPartType = (int *)
-            malloc(sizeof(int) * psObject->nParts);
+        psObject->panPartStart = STATIC_CAST(int *,
+            calloc(sizeof(int), psObject->nParts));
+        psObject->panPartType = STATIC_CAST(int *,
+            malloc(sizeof(int) * psObject->nParts));
 
         psObject->panPartStart[0] = 0;
         psObject->panPartType[0] = SHPP_RING;
 
         for( i = 0; i < nParts; i++ )
         {
-            if( panPartStart != NULL )
+            if( panPartStart != SHPLIB_NULLPTR )
                 psObject->panPartStart[i] = panPartStart[i];
 
-            if( panPartType != NULL )
+            if( panPartType != SHPLIB_NULLPTR )
                 psObject->panPartType[i] = panPartType[i];
             else
                 psObject->panPartType[i] = SHPP_RING;
@@ -1533,21 +1546,21 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
     if( nVertices > 0 )
     {
         size_t nSize = sizeof(double) * nVertices;
-        psObject->padfX = (double *) padfX ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices);
-        psObject->padfY = (double *) padfY ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices);
-        psObject->padfZ = (double *) padfZ && bHasZ ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices);
-        psObject->padfM = (double *) padfM && bHasM ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices);
-        if( padfX != NULL )
+        psObject->padfX = STATIC_CAST(double *, padfX ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices));
+        psObject->padfY = STATIC_CAST(double *, padfY ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices));
+        psObject->padfZ = STATIC_CAST(double *, padfZ && bHasZ ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices));
+        psObject->padfM = STATIC_CAST(double *, padfM && bHasM ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices));
+        if( padfX != SHPLIB_NULLPTR )
             memcpy(psObject->padfX, padfX, nSize);
-        if( padfY != NULL )
+        if( padfY != SHPLIB_NULLPTR )
             memcpy(psObject->padfY, padfY, nSize);
-        if( padfZ != NULL && bHasZ )
+        if( padfZ != SHPLIB_NULLPTR && bHasZ )
             memcpy(psObject->padfZ, padfZ, nSize);
-        if( padfM != NULL && bHasM )
+        if( padfM != SHPLIB_NULLPTR && bHasM )
         {
             memcpy(psObject->padfM, padfM, nSize);
             psObject->bMeasureIsUsed = TRUE;
@@ -1576,8 +1589,8 @@ SHPCreateSimpleObject( int nSHPType, int nVertices,
                        const double * padfZ )
 
 {
-    return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
-                             nVertices, padfX, padfY, padfZ, NULL ) );
+    return( SHPCreateObject( nSHPType, -1, 0, SHPLIB_NULLPTR, SHPLIB_NULLPTR,
+                             nVertices, padfX, padfY, padfZ, SHPLIB_NULLPTR ) );
 }
 
 /************************************************************************/
@@ -1627,15 +1640,15 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         unsigned int* panRecOffsetNew;
         unsigned int* panRecSizeNew;
 
-        panRecOffsetNew = (unsigned int *)
-            SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * nNewMaxRecords );
-        if( panRecOffsetNew == NULL )
+        panRecOffsetNew = STATIC_CAST(unsigned int *,
+            SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * nNewMaxRecords ));
+        if( panRecOffsetNew == SHPLIB_NULLPTR )
             return -1;
         psSHP->panRecOffset = panRecOffsetNew;
 
-        panRecSizeNew = (unsigned int *)
-            SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * nNewMaxRecords );
-        if( panRecSizeNew == NULL )
+        panRecSizeNew = STATIC_CAST(unsigned int *,
+            SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * nNewMaxRecords ));
+        if( panRecSizeNew == SHPLIB_NULLPTR )
             return -1;
         psSHP->panRecSize = panRecSizeNew;
 
@@ -1645,9 +1658,9 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
 /*      Initialize record.                                              */
 /* -------------------------------------------------------------------- */
-    pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
-                               + psObject->nParts * 8 + 128);
-    if( pabyRec == NULL )
+    pabyRec = STATIC_CAST(uchar *, malloc(psObject->nVertices * 4 * sizeof(double)
+                               + psObject->nParts * 8 + 128));
+    if( pabyRec == SHPLIB_NULLPTR )
         return -1;
 
 /* -------------------------------------------------------------------- */
@@ -2031,12 +2044,12 @@ static void* SHPAllocBuffer(unsigned char** pBuffer, int nSize)
 {
     unsigned char* pRet;
 
-    if( pBuffer == NULL )
+    if( pBuffer == SHPLIB_NULLPTR )
         return calloc(1, nSize);
 
     pRet = *pBuffer;
-    if( pRet == NULL )
-        return NULL;
+    if( pRet == SHPLIB_NULLPTR )
+        return SHPLIB_NULLPTR;
 
     (*pBuffer) += nSize;
     return pRet;
@@ -2056,8 +2069,8 @@ static unsigned char* SHPReallocObjectBufIfNecessary ( SHPHandle psSHP,
     }
     if( nObjectBufSize > psSHP->nObjectBufSize )
     {
-        pBuffer = (unsigned char*) realloc( psSHP->pabyObjectBuf, nObjectBufSize );
-        if( pBuffer != NULL )
+        pBuffer = STATIC_CAST(unsigned char*, realloc( psSHP->pabyObjectBuf, nObjectBufSize ));
+        if( pBuffer != SHPLIB_NULLPTR )
         {
             psSHP->pabyObjectBuf = pBuffer;
             psSHP->nObjectBufSize = nObjectBufSize;
@@ -2089,12 +2102,12 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 /*      Validate the record/entity number.                              */
 /* -------------------------------------------------------------------- */
     if( hEntity < 0 || hEntity >= psSHP->nRecords )
-        return( NULL );
+        return SHPLIB_NULLPTR;
 
 /* -------------------------------------------------------------------- */
 /*      Read offset/length from SHX loading if necessary.               */
 /* -------------------------------------------------------------------- */
-    if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX != NULL )
+    if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX != SHPLIB_NULLPTR )
     {
         unsigned int       nOffset, nLength;
 
@@ -2109,12 +2122,12 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             str[sizeof(str)-1] = '\0';
 
             psSHP->sHooks.Error( str );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
         if( !bBigEndian ) SwapWord( 4, &nOffset );
         if( !bBigEndian ) SwapWord( 4, &nLength );
 
-        if( nOffset > (unsigned int)INT_MAX )
+        if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
         {
             char str[128];
             snprintf( str, sizeof(str),
@@ -2122,9 +2135,9 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             str[sizeof(str)-1] = '\0';
 
             psSHP->sHooks.Error( str );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
-        if( nLength > (unsigned int)(INT_MAX / 2 - 4) )
+        if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
         {
             char str[128];
             snprintf( str, sizeof(str),
@@ -2132,7 +2145,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             str[sizeof(str)-1] = '\0';
 
             psSHP->sHooks.Error( str );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
         psSHP->panRecOffset[hEntity] = nOffset*2;
@@ -2155,44 +2168,46 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         /* Before allocating too much memory, check that the file is big enough */
         /* and do not trust the file size in the header the first time we */
         /* need to allocate more than 10 MB */
-        if( nNewBufSize >= 10 * 1024 * 1024 &&
-            psSHP->nBufSize < 10 * 1024 * 1024 )
-        {
-            SAOffset nFileSize;
-            psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
-            nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
-            if( nFileSize >= UINT_MAX )
-                psSHP->nFileSize = UINT_MAX;
-            else
-                psSHP->nFileSize = (unsigned int)nFileSize;
-        }
-
-        if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
-            /* We should normally use nEntitySize instead of*/
-            /* psSHP->panRecSize[hEntity] in the below test, but because of */
-            /* the case of non conformant .shx files detailed a bit below, */
-            /* let be more tolerant */
-            psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
+        if( nNewBufSize >= 10 * 1024 * 1024 )
         {
-            char str[128];
-            snprintf( str, sizeof(str),
-                        "Error in fread() reading object of size %d at offset %u from .shp file",
-                        nEntitySize, psSHP->panRecOffset[hEntity] );
-            str[sizeof(str)-1] = '\0';
+            if( psSHP->nBufSize < 10 * 1024 * 1024 )
+            {
+                SAOffset nFileSize;
+                psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
+                nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
+                if( nFileSize >= UINT_MAX )
+                    psSHP->nFileSize = UINT_MAX;
+                else
+                    psSHP->nFileSize = STATIC_CAST(unsigned int, nFileSize);
+            }
 
-            psSHP->sHooks.Error( str );
-            return NULL;
+            if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
+                /* We should normally use nEntitySize instead of*/
+                /* psSHP->panRecSize[hEntity] in the below test, but because of */
+                /* the case of non conformant .shx files detailed a bit below, */
+                /* let be more tolerant */
+                psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
+            {
+                char str[128];
+                snprintf( str, sizeof(str),
+                            "Error in fread() reading object of size %d at offset %u from .shp file",
+                            nEntitySize, psSHP->panRecOffset[hEntity] );
+                str[sizeof(str)-1] = '\0';
+
+                psSHP->sHooks.Error( str );
+                return SHPLIB_NULLPTR;
+            }
         }
 
-        pabyRecNew = (uchar *) SfRealloc(psSHP->pabyRec,nNewBufSize);
-        if (pabyRecNew == NULL)
+        pabyRecNew = STATIC_CAST(uchar *, SfRealloc(psSHP->pabyRec,nNewBufSize));
+        if (pabyRecNew == SHPLIB_NULLPTR)
         {
             snprintf( szErrorMsg, sizeof(szErrorMsg),
                      "Not enough memory to allocate requested memory (nNewBufSize=%d). "
                      "Probably broken SHP file", nNewBufSize);
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
         /* Only set new buffer size after successful alloc */
@@ -2201,9 +2216,9 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     }
 
     /* In case we were not able to reallocate the buffer on a previous step */
-    if (psSHP->pabyRec == NULL)
+    if (psSHP->pabyRec == SHPLIB_NULLPTR)
     {
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
 
 /* -------------------------------------------------------------------- */
@@ -2222,10 +2237,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         str[sizeof(str)-1] = '\0';
 
         psSHP->sHooks.Error( str );
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
 
-    nBytesRead = (int)psSHP->sHooks.FRead( psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP );
+    nBytesRead = STATIC_CAST(int, psSHP->sHooks.FRead( psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP ));
 
     /* Special case for a shapefile whose .shx content length field is not equal */
     /* to the content length field of the .shp, which is a violation of "The */
@@ -2250,7 +2265,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             str[sizeof(str)-1] = '\0';
 
             psSHP->sHooks.Error( str );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
     }
     else if( nBytesRead != nEntitySize )
@@ -2266,7 +2281,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         str[sizeof(str)-1] = '\0';
 
         psSHP->sHooks.Error( str );
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
 
     if ( 8 + 4 > nEntitySize )
@@ -2276,7 +2291,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
                  hEntity, nEntitySize);
         szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
         psSHP->sHooks.Error( szErrorMsg );
-        return NULL;
+        return SHPLIB_NULLPTR;
     }
     memcpy( &nSHPType, psSHP->pabyRec + 8, 4 );
 
@@ -2291,14 +2306,14 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         {
             psSHP->sHooks.Error( "Invalid read pattern in fast read mode. "
                                  "SHPDestroyObject() should be called." );
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
         psShape = psSHP->psCachedObject;
         memset(psShape, 0, sizeof(SHPObject));
     }
     else
-        psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
+        psShape = STATIC_CAST(SHPObject *, calloc(1,sizeof(SHPObject)));
     psShape->nShapeId = hEntity;
     psShape->nSHPType = nSHPType;
     psShape->bMeasureIsUsed = FALSE;
@@ -2316,8 +2331,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     {
         int32          nPoints, nParts;
         int                    i, nOffset;
-        unsigned char* pBuffer = NULL;
-        unsigned char** ppBuffer = NULL;
+        unsigned char* pBuffer = SHPLIB_NULLPTR;
+        unsigned char** ppBuffer = SHPLIB_NULLPTR;
 
         if ( 40 + 8 + 4 > nEntitySize )
         {
@@ -2327,7 +2342,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 /* -------------------------------------------------------------------- */
 /*     Get the X/Y bounds.                                             */
@@ -2362,7 +2377,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
         /* With the previous checks on nPoints and nParts, */
@@ -2387,7 +2402,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
         if( psShape->bFastModeReadObject )
@@ -2398,21 +2413,21 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
 
         psShape->nVertices = nPoints;
-        psShape->padfX = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
-        psShape->padfY = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
-        psShape->padfZ = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
-        psShape->padfM = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfX = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfY = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfZ = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfM = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
 
         psShape->nParts = nParts;
-        psShape->panPartStart = (int *) SHPAllocBuffer(ppBuffer, nParts * sizeof(int));
-        psShape->panPartType = (int *) SHPAllocBuffer(ppBuffer, nParts * sizeof(int));
+        psShape->panPartStart = STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
+        psShape->panPartType = STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
 
-        if (psShape->padfX == NULL ||
-            psShape->padfY == NULL ||
-            psShape->padfZ == NULL ||
-            psShape->padfM == NULL ||
-            psShape->panPartStart == NULL ||
-            psShape->panPartType == NULL)
+        if (psShape->padfX == SHPLIB_NULLPTR ||
+            psShape->padfY == SHPLIB_NULLPTR ||
+            psShape->padfZ == SHPLIB_NULLPTR ||
+            psShape->padfM == SHPLIB_NULLPTR ||
+            psShape->panPartStart == SHPLIB_NULLPTR ||
+            psShape->panPartType == SHPLIB_NULLPTR)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                     "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
@@ -2420,17 +2435,17 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
-        for( i = 0; (int32)i < nParts; i++ )
+        for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
             psShape->panPartType[i] = SHPP_RING;
 
 /* -------------------------------------------------------------------- */
 /*      Copy out the part array from the record.                        */
 /* -------------------------------------------------------------------- */
         memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
-        for( i = 0; (int32)i < nParts; i++ )
+        for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
         {
             if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
 
@@ -2446,7 +2461,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
                 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
                 psSHP->sHooks.Error( szErrorMsg );
                 SHPDestroyObject(psShape);
-                return NULL;
+                return SHPLIB_NULLPTR;
             }
             if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
             {
@@ -2456,7 +2471,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
                 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
                 psSHP->sHooks.Error( szErrorMsg );
                 SHPDestroyObject(psShape);
-                return NULL;
+                return SHPLIB_NULLPTR;
             }
         }
 
@@ -2468,7 +2483,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         if( psShape->nSHPType == SHPT_MULTIPATCH )
         {
             memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
-            for( i = 0; (int32)i < nParts; i++ )
+            for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
             {
                 if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
             }
@@ -2479,7 +2494,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
 /*      Copy out the vertices from the record.                          */
 /* -------------------------------------------------------------------- */
-        for( i = 0; (int32)i < nPoints; i++ )
+        for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
         {
             memcpy(psShape->padfX + i,
                    psSHP->pabyRec + nOffset + i * 16,
@@ -2508,7 +2523,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
 
-            for( i = 0; (int32)i < nPoints; i++ )
+            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
             {
                 memcpy( psShape->padfZ + i,
                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
@@ -2519,7 +2534,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
         else if( psShape->bFastModeReadObject )
         {
-            psShape->padfZ = NULL;
+            psShape->padfZ = SHPLIB_NULLPTR;
         }
 
 /* -------------------------------------------------------------------- */
@@ -2528,7 +2543,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 /*      big enough, but really it will only occur for the Z shapes      */
 /*      (options), and the M shapes.                                    */
 /* -------------------------------------------------------------------- */
-        if( nEntitySize >= (int)(nOffset + 16 + 8*nPoints) )
+        if( nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8*nPoints) )
         {
             memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
             memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -2536,7 +2551,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
 
-            for( i = 0; (int32)i < nPoints; i++ )
+            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
             {
                 memcpy( psShape->padfM + i,
                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
@@ -2546,7 +2561,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
         else if( psShape->bFastModeReadObject )
         {
-            psShape->padfM = NULL;
+            psShape->padfM = SHPLIB_NULLPTR;
         }
     }
 
@@ -2559,8 +2574,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     {
         int32          nPoints;
         int                    i, nOffset;
-        unsigned char* pBuffer = NULL;
-        unsigned char** ppBuffer = NULL;
+        unsigned char* pBuffer = SHPLIB_NULLPTR;
+        unsigned char** ppBuffer = SHPLIB_NULLPTR;
 
         if ( 44 + 4 > nEntitySize )
         {
@@ -2570,7 +2585,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
         memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
 
@@ -2585,7 +2600,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
         nRequiredSize = 48 + nPoints * 16;
@@ -2601,7 +2616,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
         if( psShape->bFastModeReadObject )
@@ -2613,15 +2628,15 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 
         psShape->nVertices = nPoints;
 
-        psShape->padfX = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
-        psShape->padfY = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
-        psShape->padfZ = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
-        psShape->padfM = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfX = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfY = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfZ = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfM = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
 
-        if (psShape->padfX == NULL ||
-            psShape->padfY == NULL ||
-            psShape->padfZ == NULL ||
-            psShape->padfM == NULL)
+        if (psShape->padfX == SHPLIB_NULLPTR ||
+            psShape->padfY == SHPLIB_NULLPTR ||
+            psShape->padfZ == SHPLIB_NULLPTR ||
+            psShape->padfM == SHPLIB_NULLPTR)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
@@ -2629,10 +2644,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
 
-        for( i = 0; (int32)i < nPoints; i++ )
+        for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
         {
             memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
             memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
@@ -2667,7 +2682,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
 
-            for( i = 0; (int32)i < nPoints; i++ )
+            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
             {
                 memcpy( psShape->padfZ + i,
                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
@@ -2677,7 +2692,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             nOffset += 16 + 8*nPoints;
         }
         else if( psShape->bFastModeReadObject )
-            psShape->padfZ = NULL;
+            psShape->padfZ = SHPLIB_NULLPTR;
 
 /* -------------------------------------------------------------------- */
 /*      If we have a M measure value, then read it now.  We assume      */
@@ -2685,7 +2700,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 /*      big enough, but really it will only occur for the Z shapes      */
 /*      (options), and the M shapes.                                    */
 /* -------------------------------------------------------------------- */
-        if( nEntitySize >= (int)(nOffset + 16 + 8*nPoints) )
+        if( nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8*nPoints) )
         {
             memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
             memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -2693,7 +2708,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
 
-            for( i = 0; (int32)i < nPoints; i++ )
+            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
             {
                 memcpy( psShape->padfM + i,
                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
@@ -2702,7 +2717,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             psShape->bMeasureIsUsed = TRUE;
         }
         else if( psShape->bFastModeReadObject )
-            psShape->padfM = NULL;
+            psShape->padfM = SHPLIB_NULLPTR;
     }
 
 /* ==================================================================== */
@@ -2726,10 +2741,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
         else
         {
-            psShape->padfX = (double *) calloc(1,sizeof(double));
-            psShape->padfY = (double *) calloc(1,sizeof(double));
-            psShape->padfZ = (double *) calloc(1,sizeof(double));
-            psShape->padfM = (double *) calloc(1,sizeof(double));
+            psShape->padfX = STATIC_CAST(double *, calloc(1,sizeof(double)));
+            psShape->padfY = STATIC_CAST(double *, calloc(1,sizeof(double)));
+            psShape->padfZ = STATIC_CAST(double *, calloc(1,sizeof(double)));
+            psShape->padfM = STATIC_CAST(double *, calloc(1,sizeof(double)));
         }
 
         if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
@@ -2740,7 +2755,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
-            return NULL;
+            return SHPLIB_NULLPTR;
         }
         memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
         memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
@@ -2887,7 +2902,7 @@ void SHPAPI_CALL
 SHPDestroyObject( SHPObject * psShape )
 
 {
-    if( psShape == NULL )
+    if( psShape == SHPLIB_NULLPTR )
         return;
 
     if( psShape->bFastModeReadObject )
@@ -2896,23 +2911,114 @@ SHPDestroyObject( SHPObject * psShape )
         return;
     }
 
-    if( psShape->padfX != NULL )
+    if( psShape->padfX != SHPLIB_NULLPTR )
         free( psShape->padfX );
-    if( psShape->padfY != NULL )
+    if( psShape->padfY != SHPLIB_NULLPTR )
         free( psShape->padfY );
-    if( psShape->padfZ != NULL )
+    if( psShape->padfZ != SHPLIB_NULLPTR )
         free( psShape->padfZ );
-    if( psShape->padfM != NULL )
+    if( psShape->padfM != SHPLIB_NULLPTR )
         free( psShape->padfM );
 
-    if( psShape->panPartStart != NULL )
+    if( psShape->panPartStart != SHPLIB_NULLPTR )
         free( psShape->panPartStart );
-    if( psShape->panPartType != NULL )
+    if( psShape->panPartType != SHPLIB_NULLPTR )
         free( psShape->panPartType );
 
     free( psShape );
 }
 
+/************************************************************************/
+/*                       SHPGetPartVertexCount()                        */
+/************************************************************************/
+
+static int SHPGetPartVertexCount( const SHPObject * psObject, int iPart )
+{
+    if( iPart == psObject->nParts-1 )
+        return psObject->nVertices - psObject->panPartStart[iPart];
+    else
+        return psObject->panPartStart[iPart+1] - psObject->panPartStart[iPart];
+}
+
+/************************************************************************/
+/*                      SHPRewindIsInnerRing()                          */
+/************************************************************************/
+
+static int SHPRewindIsInnerRing( const SHPObject * psObject,
+                                 int iOpRing )
+{
+/* -------------------------------------------------------------------- */
+/*      Determine if this ring is an inner ring or an outer ring        */
+/*      relative to all the other rings.  For now we assume the         */
+/*      first ring is outer and all others are inner, but eventually    */
+/*      we need to fix this to handle multiple island polygons and      */
+/*      unordered sets of rings.                                        */
+/*                                                                      */
+/* -------------------------------------------------------------------- */
+
+    /* Use point in the middle of segment to avoid testing
+     * common points of rings.
+     */
+    const int iOpRingStart = psObject->panPartStart[iOpRing];
+    double dfTestX = ( psObject->padfX[iOpRingStart] +
+                       psObject->padfX[iOpRingStart + 1] ) / 2;
+    double dfTestY = ( psObject->padfY[iOpRingStart] +
+                       psObject->padfY[iOpRingStart + 1] ) / 2;
+
+    int bInner = FALSE;
+    int iCheckRing;
+    for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
+    {
+        int nVertStartCheck, nVertCountCheck;
+        int iEdge;
+
+        if( iCheckRing == iOpRing )
+            continue;
+
+        nVertStartCheck = psObject->panPartStart[iCheckRing];
+        nVertCountCheck = SHPGetPartVertexCount(psObject, iCheckRing);
+
+        for( iEdge = 0; iEdge < nVertCountCheck; iEdge++ )
+        {
+            int iNext;
+
+            if( iEdge < nVertCountCheck-1 )
+                iNext = iEdge+1;
+            else
+                iNext = 0;
+
+            /* Rule #1:
+             * Test whether the edge 'straddles' the horizontal ray from
+             * the test point (dfTestY,dfTestY)
+             * The rule #1 also excludes edges colinear with the ray.
+             */
+            if ( ( psObject->padfY[iEdge+nVertStartCheck] < dfTestY
+                    && dfTestY <= psObject->padfY[iNext+nVertStartCheck] )
+                    || ( psObject->padfY[iNext+nVertStartCheck] < dfTestY
+                        && dfTestY <= psObject->padfY[iEdge+nVertStartCheck] ) )
+            {
+                /* Rule #2:
+                 * Test if edge-ray intersection is on the right from the
+                 * test point (dfTestY,dfTestY)
+                 */
+                double const intersect =
+                    ( psObject->padfX[iEdge+nVertStartCheck]
+                        + ( dfTestY - psObject->padfY[iEdge+nVertStartCheck] )
+                        / ( psObject->padfY[iNext+nVertStartCheck] -
+                            psObject->padfY[iEdge+nVertStartCheck] )
+                        * ( psObject->padfX[iNext+nVertStartCheck] -
+                            psObject->padfX[iEdge+nVertStartCheck] ) );
+
+                if (intersect  < dfTestX)
+                {
+                    bInner = !bInner;
+                }
+            }
+        }
+    } /* for iCheckRing */
+    return bInner;
+}
+
 /************************************************************************/
 /*                          SHPRewindObject()                           */
 /*                                                                      */
@@ -2942,100 +3048,33 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
 /* -------------------------------------------------------------------- */
     for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
     {
-        int      bInner, iVert, nVertCount, nVertStart, iCheckRing;
-        double   dfSum, dfTestX, dfTestY;
-
-/* -------------------------------------------------------------------- */
-/*      Determine if this ring is an inner ring or an outer ring        */
-/*      relative to all the other rings.  For now we assume the         */
-/*      first ring is outer and all others are inner, but eventually    */
-/*      we need to fix this to handle multiple island polygons and      */
-/*      unordered sets of rings.                                        */
-/*                                                                      */
-/* -------------------------------------------------------------------- */
-
-        /* Use point in the middle of segment to avoid testing
-         * common points of rings.
-         */
-        dfTestX = ( psObject->padfX[psObject->panPartStart[iOpRing]]
-                    + psObject->padfX[psObject->panPartStart[iOpRing] + 1] ) / 2;
-        dfTestY = ( psObject->padfY[psObject->panPartStart[iOpRing]]
-                    + psObject->padfY[psObject->panPartStart[iOpRing] + 1] ) / 2;
-
-        bInner = FALSE;
-        for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
-        {
-            int iEdge;
-
-            if( iCheckRing == iOpRing )
-                continue;
-
-            nVertStart = psObject->panPartStart[iCheckRing];
+        int      bInner, iVert, nVertCount, nVertStart;
+        double   dfSum;
 
-            if( iCheckRing == psObject->nParts-1 )
-                nVertCount = psObject->nVertices
-                    - psObject->panPartStart[iCheckRing];
-            else
-                nVertCount = psObject->panPartStart[iCheckRing+1]
-                    - psObject->panPartStart[iCheckRing];
+        nVertStart = psObject->panPartStart[iOpRing];
+        nVertCount = SHPGetPartVertexCount(psObject, iOpRing);
 
-            for( iEdge = 0; iEdge < nVertCount; iEdge++ )
-            {
-                int iNext;
+        if (nVertCount < 2)
+            continue;
 
-                if( iEdge < nVertCount-1 )
-                    iNext = iEdge+1;
-                else
-                    iNext = 0;
-
-                /* Rule #1:
-                 * Test whether the edge 'straddles' the horizontal ray from the test point (dfTestY,dfTestY)
-                 * The rule #1 also excludes edges colinear with the ray.
-                 */
-                if ( ( psObject->padfY[iEdge+nVertStart] < dfTestY
-                       && dfTestY <= psObject->padfY[iNext+nVertStart] )
-                     || ( psObject->padfY[iNext+nVertStart] < dfTestY
-                          && dfTestY <= psObject->padfY[iEdge+nVertStart] ) )
-                {
-                    /* Rule #2:
-                     * Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
-                     */
-                    double const intersect =
-                        ( psObject->padfX[iEdge+nVertStart]
-                          + ( dfTestY - psObject->padfY[iEdge+nVertStart] )
-                          / ( psObject->padfY[iNext+nVertStart] - psObject->padfY[iEdge+nVertStart] )
-                          * ( psObject->padfX[iNext+nVertStart] - psObject->padfX[iEdge+nVertStart] ) );
-
-                    if (intersect  < dfTestX)
-                    {
-                        bInner = !bInner;
-                    }
-                }
-            }
-        } /* for iCheckRing */
+        bInner = SHPRewindIsInnerRing(psObject, iOpRing);
 
 /* -------------------------------------------------------------------- */
 /*      Determine the current order of this ring so we will know if     */
 /*      it has to be reversed.                                          */
 /* -------------------------------------------------------------------- */
-        nVertStart = psObject->panPartStart[iOpRing];
-
-        if( iOpRing == psObject->nParts-1 )
-            nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
-        else
-            nVertCount = psObject->panPartStart[iOpRing+1]
-                - psObject->panPartStart[iOpRing];
-
-        if (nVertCount < 2)
-            continue;
 
-        dfSum = psObject->padfX[nVertStart] * (psObject->padfY[nVertStart+1] - psObject->padfY[nVertStart+nVertCount-1]);
+        dfSum = psObject->padfX[nVertStart] *
+                        (psObject->padfY[nVertStart+1] -
+                         psObject->padfY[nVertStart+nVertCount-1]);
         for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
         {
-            dfSum += psObject->padfX[iVert] * (psObject->padfY[iVert+1] - psObject->padfY[iVert-1]);
+            dfSum += psObject->padfX[iVert] * (psObject->padfY[iVert+1] -
+                                               psObject->padfY[iVert-1]);
         }
 
-        dfSum += psObject->padfX[iVert] * (psObject->padfY[nVertStart] - psObject->padfY[iVert-1]);
+        dfSum += psObject->padfX[iVert] * (psObject->padfY[nVertStart] -
+                                           psObject->padfY[iVert-1]);
 
 /* -------------------------------------------------------------------- */
 /*      Reverse if necessary.                                           */